setTimeout阻止子进程中的Promise

问题描述

我在子进程的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

解决方法

其原因是spawnSync直到子进程以stated in the documentation的身份完全关闭后才会返回:

child_process.spawnSync()方法通常与 child_process.spawn(),但函数不会 返回直到子进程完全关闭。 [...]

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

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

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