2016-11-25 23 views
0

鑑於在那裏我使用的NodeJS readline庫遍歷STDIN流中的每一行,做一些關於它的處理,並寫回到STDOUT在下面的示例中的情況:基於事件的讀取功能是否可能無序運行?

var rl = readline.createInterface({ 
    input: process.stdin, 
    output: process.stdout, 
    terminal: false 
}); 
function my_function(line) { 
    var output = ...(line); 
    process.stdout.write(output); 
} 
rl.on('line', my_function); 

我擔心我所做的處理將花費大量不同的時間,具體取決於行內容,因此某些行將很快返回,而其他行則需要一些時間來整理。 my_function()是否可能運行不正常,從而導致輸出流被擾亂?我應該考慮使用某種類型的同步循環而不是此異步事件處理程序嗎?

回答

2

JavaScript執行本身是單線程的,所以只要您只在事件處理程序中執行同步操作,就沒有問題。

如果你執行事件處理中異步操作,那麼有可能是另一個'line'事件可能你的異步操作(或多個)之前發出的是完整的。在這種情況下,一旦完成異步操作,您需要先執行rl.pause(),然後再執行rl.resume()。但是,這並非萬無一失,因爲如果從輸入流讀取的當前數據塊有多個換行符,'line'事件仍然可以在rl.pause()之後發出。

因此,如果您在事件處理程序內部執行異步操作,那麼您最好自己從流中讀取數據,以便更好地控制解析行爲。這實際上很容易做到,例如:

function parseStream(stream, callback) { 
    // Assuming all stream data is text and not binary ... 
    var buffer = ''; 

    var RE_EOL = /\r?\n/g; 

    stream.on('data', function(data) { 
    buffer += data; 
    processBuffer(); 
    }); 

    stream.on('end', callback); 

    stream.on('error', callback); 

    function processBuffer() { 
    var idx = RE_EOL.exec(buffer); 
    if (~idx) { 
     // Found a line ending 

     var line = buffer.slice(0, RE_EOL.index); 
     buffer = buffer.slice(RE_EOL.index + RE_EOL[0].length); 

     stream.pause(); 
     callback(null, line, processBuffer); 
    } else { 
     stream.resume(); 
    } 
    } 
} 

// ... 

processStream(process.stdin, function(err, line, done) { 
    if (err) throw err; 

    if (line === undefined) { 
    // No more data will be available (stream ended) 
    console.log('(Stream ended!)'); 
    return; 
    } 

    // Do something with `line` 
    console.log(line); 

    // Call `done()` whenever your async operation(s) are all finished 
    done(); 
}); 
+0

感謝您的解釋和建議如何繼續。坦率地說,儘管我對這個模板的轉換程度有點不安,但它只是一次一行地遍歷一條流。我認爲我有點習慣Unix操作系統的普通操作。我想知道如果我在其他方面的迭代中做得更好,並且一次只對這個特定的腳本進行一次調用。這將是很多的調用,但考慮到庫的開銷,我實際上正在做的解析不會那麼重要。 – Caleb

+0

你能澄清一點嗎?你說過運行'rl.pause()'「並非萬無一失」,但是如果我嚴格遵守那個事件處理程序中的同步函數調用呢?如果我沒有做任何事情,我是否足夠安全地使用我的代碼? – Caleb

+0

如果你只做同步操作,你不必擔心改變什麼,因爲js是單線程的,這意味着當你的事件處理函數被執行時,沒有其他的js可以被執行。這意味着不需要暫停/恢復readline實例或輸入流。但是如果你做過異步操作,你可能會需要類似我給出的代碼示例。 – mscdex