如何将节点的child_process.exec()与promise一起使用

问题描述 投票:0回答:2

我尝试使用node.js(docker exec命令)顺序执行长进程。

我愿意:

const childProcess = require('child_process');

const execWithPromise = async command => {
    return new Promise(async resolve => {
        const process = childProcess.exec(command);

        process.on('exit', err => resolve(err));
        process.on('close', err => resolve(err));
    });
};

const run = async () => {
    await execWithPromise('/usr/local/bin/docker exec -i -t cucumber node long-running-script.js');
    await execWithPromise('/usr/local/bin/docker exec -i -t cucumber node long-running-script.js');
};

run();

但是在这两种情况下,promise 都会立即得到解决,结果都是 1。该命令在命令行上运行得很好。

为什么立即返回?

node.js exec child-process
2个回答
13
投票

child_process.exec
期望回调作为第二个或第三个参数。它不返回承诺。根据您的用例和节点版本,您有几种选择。以下工作适用于节点 16.x

使用回调并返回解析结果。

const execWithPromise = command =>
  new Promise((resolve, reject) => {
    childProcess.exec(command, (err, stout, sterr) => {
      if(err) {
        reject(sterr)
      } else {
        resolve(stout)
      }
    })
  })

使用spawn代替(保留大部分代码)

const execWithPromise = command => 
  new Promise((resolve, reject) => {
      const process = childProcess.spawn(command);
      let data = '';
      let error = '';
      process.stdout.on('data', stdout => {
        data += stdout.toString();
      });
      process.stderr.on('data', stderr => {
        error += stderr.toString();
      });
      process.on('error', err => {
        reject(err);
      })
      process.on('close', code => {
        if (code !== 0) {
          reject(error)
        } else {
          resolve(data)
        }
        process.stdin.end();
      });
  });

使用execSync

const execWithPromise = command => childProcess.execSync(command).toString();

3
投票

这是当前 Node.js 的答案:

打字稿

对于 TypeScript,在

app.ts
:

import { exec as lameExec } from "child_process";
const exec = promisify(lameExec);
const { stdout, stderr } = await exec(`some command to run`);

然后您可以使用 esrun (

npm i @digitak/esrun
) 运行它,它支持顶级等待:

npx esrun app.ts

JavaScript

在 JS 中调用文件

app.mjs
并使用

运行它

node app.mjs

© www.soinside.com 2019 - 2024. All rights reserved.