我有一个干净的Windows 8.1盒子,安装了lates node.js(v0.10.29)。我在两个文件中有以下测试代码:
a.js
var sub = require('child_process').spawn('node', ['b.js'], {silent: true});
sub.stdout.on("data", function (data) {console.log(data.toString());});
b.js
console.log("DEBUG 1");
console.log("DEBUG 2");
process.exit();
如果我通过以下方式执行a.ja
:
node a.js
我将在控制台输出中看到“DEBUG 1” - 但不是“DEBUG 2”。如果我删除process.exit()
,则两行都将正确显示。这种奇怪的行为发生在fork
和spawn
。
任何提示?相同的代码在linux上没有问题。
更新02.07.2014
似乎这不是exit()和log()之间的竞争条件,因为将其更改为纯序列会产生相同的错误:
function print(text, next) { console.log(text); next(); }
print("DEBUG 1", function () {
print("DEBUG 2", function () {
process.exit();
});
});
更新03.07.2014
silent
未列在spawn()
文档中,但可以正常使用。它列在fork
文档中,正如我之前提到的,此问题与fork
相同。
似乎如果我在上一次输出和process.exit()
之间引入延迟都能正常工作:
console.log("DEBUG 1");
console.log("DEBUG 2");
setTimeout(function () {process.exit();}, 10000);
但问题只有在我管道输出到父进程时才会显现:如果我删除了silent
,两条消息都会正确显示,即使没有延迟,所以管道最有可能是错误的沟通,而不是process.exit
。
更多更新03.07.2014
评论中推测process.exit()
可能会终止这两个进程(a.ja
和b.ja
)。不,它仅终止衍生/分叉过程,我通过向setTimeout
添加无限a.js
来检查这一点,它在b.ja
终止后仍然可以正常工作,但仍然没有“DEBUG 2”行。< / p>
答案 0 :(得分:3)
主要编辑为清晰起见:
您遇到的问题是console.log('DEBUG2')
和process.end()
之间的并发事件,其中两个事件同时被调用(几乎),但process.end()
具有更高的优先级,完成后,让sub
停止听事件,然后停止打印DEBUG2:
在您的代码中:
a.js |b.js
start
spawn |start
listen |send('DEBUG1')
get DEBUG1 |send('DEBUG2')
start the event |send KILL
print DEBUG1 |
get DEBUG2
start the event
get KILL
kill b.js //DEBUG2 haven t been printed
现在,如果你减慢process.end:
b.js:
console.log('DEBUG1');
console.log('DEBUG2');
setTimeout(function () {
process.end();
}, 1000);
a.js |b.js
start
spawn |start
listen |send('DEBUG1')
get DEBUG1 |send('DEBUG2')
start the event |wait
print DEBUG1 |wait
get DEBUG2 |send KILL
start the event
print DEBUG2
get KILL
kill b.js
但这太麻烦了,你不知道有多少&#34;等等#34;将有。另一个解决方案是使b.js继承stdout,因此没有事件要做:
a.js:
var sub = require('child_process').spawn('node', ['b.js'], {stdio:[process.stdin, process.stdout, process.stderr]});
a.js |b.js
start
spawn |start
listen |print DEBUG1
|print DEBUG2
|send KILL
get KILL |
kill b.js
现在,没有容易出错的代码,但你无法获得a.js中打印的内容。我认为使用process.nextTick的另一个解决方案可以工作,但我不知道它是如何工作的。
编辑:
process.exit()
杀死b.js,这是预期的行为。 a.js看到data
事件结束,所以有一个空的事件循环,所以自杀:)