我尝试使用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。该命令在命令行上运行得很好。
为什么立即返回?
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();
对于 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
在 JS 中调用文件
app.mjs
并使用 运行它
node app.mjs