2015-02-17 61 views
1

我開始學習和使用節點,我喜歡它,但我不確定某些功能是如何工作的。也許你可以幫我解決一個這樣的問題:child_process spawn nodejs中競態條件的可能性

我想從我的節點服務器產生本地腳本和程序時,休息命令。看着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

這不是一個競爭條件。 Node.js是單線程的,並以先到先得的方式處理事件。新事件放在事件循環的末尾。節點將以同步方式執行您的代碼,其中一部分將涉及設置事件發射器。當這些事件發射器發出事件時,它們將被放到隊列的末尾,並且直到節點完成執行它當前正在工作的任何一段代碼纔會被處理,這恰好與註冊偵聽器的代碼相同。因此,在處理事件之前,監聽器將始終被註冊。

+0

謝謝Yuri,這對我所問的情況有意義,我問了從主服務器代碼中產生了哪些spawn。只是爲了得到更多的澄清,如果我產生了一個反過來催生了孩子的孩子,你的邏輯還會持續嗎? – ThinkBonobo 2015-02-18 02:06:39

+0

沒問題。我不明白爲什麼它不會。 – 2015-02-18 02:13:01

+0

我不明白這一點。節點只能控制自己的線程模型,它不能控制它產生的子進程。當我遍歷一些代碼來生成子進程並檢查spawn返回的值時,只要到達下一個語句就已經有一個進程ID,這意味着進程在我的任何處理程序之前運行註冊(至少在Windows上)。這意味着你錯了。 – 2017-07-13 20:45:24