异步函数不等待 Node.js 中子进程的结果

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

Javascript/Node初学者。

我查阅了几篇文章 (, Link 2, Link 3),但我在以下 Node.js 代码中遇到错误:

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();

控制台输出:

RESULT: undefined
return value in fxn: 2nd

为什么我的await不等待sh()的结果?我希望它 return 值“2nd”。

(bash 脚本无关紧要;它只是 echo

await 你的函数,但那个函数并不是真正的 async。当一个函数前面有 async 关键字时,它实际上所做的是将整个函数包装到 Promise 实例中。但是如果你不能正确处理这个函数中的内容,它就不会工作。

在您的情况下,您需要手动 return Promise 个实例。它接受带有 resolve & reject 参数的回调。您可以调用 resolve 来解决承诺:

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);
            })
    })
}

由于 execFile 不是 return Promise,并且 async/await 是使用 promise 的语法糖,您的代码永远不会“等待”execFile 运行

另一种方法是使用 node.js“promisify”

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

那么你的sh函数就可以

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);
}

或者,对 function sh

使用 async/await
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;
  }
}