我开始学习和使用节点,我喜欢它,但我不确定某些功能是如何工作的。也许你可以帮我解决一个这样的问题:
我希望在休息命令时从我的节点服务器生成本地脚本和程序。看看fs库我看到下面的示例如何生成子进程并在其上添加一些管道/事件处理程序。
var spawn = require('child_process').spawn,
ps = spawn('ps', ['ax']),
grep = spawn('grep', ['ssh']);
ps.stdout.on('data', function (data) {
grep.stdin.write(data);
});
ps.stderr.on('data', function (data) {
console.log('ps stderr: ' + data);
});
ps.on('close', function (code) {
if (code !== 0) {
console.log('ps process exited with code ' + code);
}
grep.stdin.end();
});
grep.stdout.on('data', function (data) {
console.log('' + data);
});
grep.stderr.on('data', function (data) {
console.log('grep stderr: ' + data);
});
grep.on('close', function (code) {
if (code !== 0) {
console.log('grep process exited with code ' + code);
}
});
对我来说奇怪的是,我不明白如何保证在程序开始运行之前注册事件处理程序代码。它并不像那里的“简历”那样。你跑来启动孩子的功能。这不是竞争条件吗?当然,条件将微不足道,并且几乎从未打过,因为它之后会有如此短暂的代码剪切,但如果是这样的话,我宁愿不按照良好习惯进行编码。
所以: 1)如果不是比赛条件,为什么? 2)如果是竞争条件我怎么能以正确的方式写出来?
谢谢你的时间!
答案 0 :(得分:1)
这不是竞争条件。 Node.js是单线程的,以先到先得的方式处理事件。在事件循环结束时放置新事件。 Node将以同步方式执行您的代码,其中一部分将涉及设置事件发射器。当这些事件发射器发出事件时,它们将被放到队列的末尾,并且在Node完成执行其当前正在处理的任何代码片段之前将不会被处理,这恰好是注册侦听器的相同代码。因此,在处理事件之前,将始终注册侦听器。
答案 1 :(得分:0)
鉴于已接受答案的评论中存在轻微冲突和含糊不清,下面的示例和输出告诉我两件事:
spawn
返回的节点对象)也不会发出事件。两者都很明显。冲突是w.r.t. OP的问题的解释:-
实际上是“是”,如果需要考虑实际子进程的副作用,这就是数据争用情况的缩影。但是“不”,就IPC管道管道而言,没有数据争用。当上下文完成时(如前所述),数据将被写入缓冲区并作为(更大)blob进行检索。
下面看到的第一个数据事件在我们阻塞时不会被子进程推送1个而是将5个块推入stdout。因此没有丢失。
样本:
let t = () => (new Date()).toTimeString().split(' ')[0]
let p = new Promise(function (resolve, reject) {
console.log(`[${t()}|info] spawning`);
let cp = spawn('bash', ['-c', 'for x in `seq 1 1 10`; do printf "$x\n"; sleep 1; done']);
let resolved = false;
if (cp === undefined)
reject();
cp.on('error', (err) => {
console.log(`error: ${err}`);
reject(err);
});
cp.stdout.on('data', (data) => {
if (!resolved) {
console.log(`[${t()}|info] spawn succeeded`);
resolved = true;
resolve();
}
process.stdout.write(`[${t()}|data] ${data}`);
});
let ts = parseInt(Date.now() / 1000);
while (parseInt(Date.now() / 1000) - ts < 5) {
// waste some cycles in the current context
ts--; ts++;
}
console.log(`[${t()}|info] synchronous time wasted`);
});
Promise.resolve(p);
输出:
[18:54:18|info] spawning
[18:54:23|info] synchronous time wasted
[18:54:23|info] spawn succeeded
[18:54:23|data] 1
2
3
4
5
[18:54:23|data] 6
[18:54:24|data] 7
[18:54:25|data] 8
[18:54:26|data] 9
[18:54:27|data] 10