I am trying to make one function that returns a 1 after a command from terminal is fully executed.
Any idea how to do it?
This is my code:
const speed = async () => {
try {
exec(`speedtest`, (error, stdout, stderr) => {
if (error) {
// console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
console.log(stdout);
} catch (error) {
console.log('error')
}
Knowing that speedtest command takes sometime to print the whole output, i would like to proceed to other line of code only if the command is fully executed.
CodePudding user response:
You can use Promises for that:
const { exec } = require('child_process');
const speed = () => new Promise((resolve, reject) => {
try {
exec(`speedtest`, (error, stdout, stderr) => {
if (error) {
reject(error);
} else if (stderr) {
reject(stderr);
} else {
const downloadSpeed = stdout.match(/Download:\s (\d (\.\d )?)/i);
const uploadSpeed = stdout.match(/Upload:\s (\d (\.\d )?)/i);
const speed = {
download: downloadSpeed? Number(downloadSpeed[1]) : null,
upload: uploadSpeed? Number(uploadSpeed[1]) : null,
}
resolve(speed);
}
});
} catch (error) {
reject(error)
}
});
speed()
.then(speed => console.log('got resolve:', speed))
.catch(error => console.log('got reject:', error));
Promise will be resolved after something will be in stdout
.
If You want to wait for something special, you can use regular expressions and add timeout
arg:
const {
exec
} = require('child_process');
const speed = (timeout = 60000) => new Promise((resolve, reject) => {
try {
const searchingString = 'Result URL:';
let fullOutput = '';
let finished = false;
setTimeout(() => {
if (finished) return;
reject(new Error('Timeout'));
}, timeout);
exec(`speedtest`, (error, stdout, stderr) => {
if (error) {
reject(error);
} else if (stderr) {
reject(stderr);
} else {
fullOutput = stdout;
if (fullOutput.indexOf(searchingString) === -1) {
return;
}
finished = true;
const downloadSpeed = fullOutput.match(/Download:\s (\d (\.\d )?)/i);
const uploadSpeed = fullOutput.match(/Upload:\s (\d (\.\d )?)/i);
const speed = {
download: downloadSpeed ? Number(downloadSpeed[1]) : null,
upload: uploadSpeed ? Number(uploadSpeed[1]) : null,
}
resolve(speed);
}
});
} catch (error) {
reject(error)
}
});
speed()
.then(speed => console.log('got resolve:', speed))
.catch(error => console.log('got reject:', error));
The other way is to use listeners
on child process:
const {
exec
} = require('child_process');
const speed = (timeout = 60000) => new Promise((resolve, reject) => {
try {
let fullOutput = '';
let timer = setTimeout(() => {
if (finished) return;
reject(new Error('Timeout'));
}, timeout);
const child = exec(`speedtest`, (error, stdout, stderr) => {
if (error) {
reject(error);
} else if (stderr) {
reject(stderr);
} else {
fullOutput = stdout;
}
});
child.on('close', () => {
clearTimeout(timer);
const downloadSpeed = fullOutput.match(/Download:\s (\d (\.\d )?)/i);
const uploadSpeed = fullOutput.match(/Upload:\s (\d (\.\d )?)/i);
const speed = {
download: downloadSpeed ? Number(downloadSpeed[1]) : null,
upload: uploadSpeed ? Number(uploadSpeed[1]) : null,
}
resolve(speed);
});
child.on('error', reject);
} catch (error) {
reject(error)
}
});
speed()
.then(speed => console.log('got resolve:', speed))
.catch(error => console.log('got reject:', error));