简体   繁体   中英

Async function not awaiting the result of child process in Node.js

Javascript/Node beginner here.

I've consulted several posts ( Link 1 , Link 2 , Link 3 ) but I am getting an error on my following Node.js code:

const execFile = require('child_process').execFile;

async function execute(){
  let result = await sh();
  console.log("RESULT: " + result);
}

async function sh(){
  execFile('./demo-files/demo.sh', ['1st', '2nd', '3rd'], 
  function(err, data){
    let returnValue;
    if(err){
      returnValue = "ERROR:\n" + err;
    }
    else {
      returnValue = data.toString();
    }
    console.log("return value in fxn: " + returnValue);
    return returnValue;
  });
}

execute();

The console output:

RESULT: undefined
return value in fxn: 2nd

Why does my await not wait for the result of sh() ? I expected it to return the value "2nd".

(The bash script is inconsequential; it's just echo $2 )

You await your function, but that function is not really async . When a function has async keyword before it, what it actually does is wrap the whole function to Promise instance. But if you won't handle what is inside this function correctly, it won't work.

In your case, you need return Promise instance manually. It accepts callback with resolve & reject arguments. And you can call resolve to resolve the promise:

function sh() {
    return new Promise(resolve => {
        execFile('./demo-files/demo.sh', ['1st', '2nd', '3rd'],
            function (err, data) {
                let returnValue;
                if (err) {
                    returnValue = "ERROR:\n" + err;
                }
                else {
                    returnValue = data.toString();
                }
                console.log("return value in fxn: " + returnValue);
                resolve(returnValue);
            })
    })
}

Since execFile doesn't return a Promise, and async/await is syntax sugar for working with promises, your code can never "wait" for the execFile to run

An alternative is to use node.js "promisify"

const util = require('util');
const execFile = util.promisify(require('child_process').execFile);

then your sh function can be

const util = require('util');
const execFile = util.promisify(require('child_process').execFile);

async function execute(){
  let result = await sh();
  console.log("RESULT: " + result);
}

function sh(){
  return execFile('./demo-files/demo.sh', ['1st', '2nd', '3rd'])
  .then(data => data.toString())
  .catch(err => "ERROR:\n" + err);
}

Or, using async/await for function sh

const util = require('util');
const execFile = util.promisify(require('child_process').execFile);

async function execute(){
  let result = await sh();
  console.log("RESULT: " + result);
}

async function sh(){
  try {
    const data = await execFile('./demo-files/demo.sh', ['1st', '2nd', '3rd']);
    return data.toString();
  } catch (err) {
    return "ERROR:\n" + err;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM