首页 > 解决方案 > setTimeout 在子进程中阻止 Promise

问题描述

setTimeout我在子进程的承诺内部遇到了一个奇怪的问题。

这些是我的文件:

index.js

const {spawnSync} = require('child_process');
const {resolve} = require('path');

const timeoutPromiseModule = resolve(__dirname, '.', 'timeout-promise');
const {stdout} = spawnSync('node', [timeoutPromiseModule]);
console.log(stdout.toString());

timeout-promise.js

Promise.race([
    Promise.resolve(),
    new Promise((resolve, reject) => {
      setTimeout(() => {reject('too long')}, 10000);
    })
])
.then(x=> console.log('resolved'))
.catch(e => console.log('rejected'));

当我运行时,node index.js我希望输出会立即打印,但实际发生的是输出挂起,直到setTimeout子进程调用 的回调。

这是什么原因造成的,如何解决?

我猜这与子进程的事件循环有关,它阻止子进程关闭直到消息为空?

为方便起见,我将代码上传到 GitHub:

https://github.com/alexkubica/promise-race-settimeout-blocking-inside-child-process

标签: node.jsasynchronouspromisesettimeoutchild-process

解决方案


原因是spawnSync在子进程完全关闭之前不会返回,如文档中所述

child_process.spawnSync() 方法通常与 child_process.spawn() 相同,只是该函数在子进程完全关闭之前不会返回。[...]

请注意,仅当事件循环的队列中没有更多待处理任务时,节点脚本才会退出,在这种情况下,会在超时解决后发生。

您可以切换到spawn查看立即解决的承诺输出:

const res = spawn('node', [timeoutPromiseModule]);

res.stdout.on('data', (data) => {
    console.log(`stdout: ${data}`);
});

res.on('close', (code) => {
    console.log(`child process exited with code ${code}`);
});

推荐阅读