I have multiple functions inside my route and want to execute them in order for eg the control should only move to the next function if the previous function has been successfully executed. For eg refer the below code, I wish to execute task1 first followed by task 2 and so on. Setting a timeout or await doesn't seem to be an efficient way, do I need to add async functions or something similar?
Code.js
var task1 = cp.exec('docker images', function (error, stdout, stderr) {
console.log('Version: ' +version);
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
var task2 = cp.exec('docker pull mongo:'+version, function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
var task3 = cp.exec('docker run -d -p '+port2+':27017 -v '+volumeLoc+' --name '+containerName+' mongo:'+version, function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
var task4 = cp.exec('docker ps | grep mongo', function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
I have multiple functions inside my route and want to execute them in order for eg the control should only move to the next function if the previous function has been successfully executed. For eg refer the below code, I wish to execute task1 first followed by task 2 and so on. Setting a timeout or await doesn't seem to be an efficient way, do I need to add async functions or something similar?
Code.js
var task1 = cp.exec('docker images', function (error, stdout, stderr) {
console.log('Version: ' +version);
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
var task2 = cp.exec('docker pull mongo:'+version, function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
var task3 = cp.exec('docker run -d -p '+port2+':27017 -v '+volumeLoc+' --name '+containerName+' mongo:'+version, function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
var task4 = cp.exec('docker ps | grep mongo', function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
Share
Improve this question
asked May 7, 2020 at 6:19
nomadev95nomadev95
1251 silver badge13 bronze badges
2
- simpler way is to call each other function on previous function's callback. – code-jaff Commented May 7, 2020 at 6:22
- You are not understanding that node will execute EVERYTHING async, unless told otherwise. nodejs/en/knowledge/getting-started/control-flow/… – Kasey Chang Commented May 7, 2020 at 6:23
4 Answers
Reset to default 4First turn each task into a function that returns a promise:
function task1() {
let resolve, reject;
const promise = new Promise((rs, rj) => { resolve = rs; reject = rj; });
cp.exec('docker images', function (error, stdout, stderr) {
console.log('Version: ' +version);
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
reject(error);
} else {
resolve();
}
});
return promise;
}
Then wrap them all inside an async function:
async function main() {
try {
await task1();
await task2();
} catch (err) {
// handle error here
}
}
try cp.execSync
function, it do the same thing but in synchronous manner https://nodejs/api/child_process.html#child_process_child_process_execsync_mand_options
example of usage
try {
const result1 = cp.execSync('docker images');
console.log('result1', result1);
const result2 = cp.execSync('docker pull mongo');
console.log('result2', result2);
} catch(e) {
console.error('error occured', e);
}
You can consider using Promise chain for this type of execution. For example,
var tas1 = function(){
return new Promise(function(resolve) {
// Your code
});
}
var task2 = function(){
return new Promise(function(resolve){
// Your code
});
}
var task3 = function(){
return new Promise(function(resolve){
// Your code
});
}
//Start sequential GET using chained promises
task1().then(task2).then(task3);
You need either callbacks or async/await.
You have already callbacks, you could call the next function right after the error checks (I guess they are somehow dependent, so maybe only exec the next step after a succesful previous mand)
if (error !== null) {
console.log('exec error: ' + error);
} else {
task2(); //but has to be defined upfront
}
You could also use util promisify:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
try {
const { stdout, stderr } = await exec('docker images') {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
}
catch (error) {
console.log('exec error: ' + error);
}
// and then the other steps