setTimeout 在子进程中阻止 Promise

setTimeout blocks Promise inside a child process

我在子进程的承诺中遇到 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

原因是 spawnSync 不会 return 直到子进程完全关闭 stated in the documentation:

The child_process.spawnSync() method is generally identical to child_process.spawn() with the exception that the function will not return until the child process has fully closed. [...]

请注意,节点脚本只有在事件循环队列中有 no more pending tasks 时才会退出,在这种情况下会在超时解决后发生。

您可以切换到 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}`);
});