2017-12-03 228 views
0

有人可以解釋以下行爲嗎?這當然是由於異步I/O造成的,但下面的代碼基於很多簡單的例子,其中一些來自SO,顯然這裏沒有討論這個問題,這裏沒有按照預期讀取流。Node.js ReadableStream和異步事件監聽器

有什麼解決方案?我試圖從第一原理中理解底層問題,所以請不要建議我使用發佈的npm stream-> string包。謝謝。

鑑於文件n.js

'use strict'; 

const streamToString = (s, cb) => { 
    const chunks = [] 

    s.on('readable',() => { 
    console.log('data') 
    let chunk 
    while(null !== (chunk = s.read())) { 
     chunks.push(chunk) 
    } 
    }) 
    s.on('end',() => { 
    console.log('end') 
    cb(Buffer.concat(chunks).toString()) 
    }) 
} 

let o 
const f = (str) => { 
    o = JSON.parse(str) 
} 

const fs = require('fs') 
const rs = fs.createReadStream('t.json') 
streamToString(rs, f) 

console.log('o = ' + o) 

在終端

$ uname -a 
Linux bsh 4.10.0-40-generiC#44~16.04.1-Ubuntu SMP Thu Nov 9 15:37:44 UTC  2017 x86_64 x86_64 x86_64 GNU/Linux 
$ node --version 
v6.12.0 
$ node n.js 
o = undefined 
data 
data 
end 

輸出適用於任何非空輸入文件,包含簡單驗證JSON。

我也試圖與「讀」事件,即

s.on('read', (chunk) => { 
    console.log('data') 
    chunks.push(chunk) 
    }) 

和輸出

o = undefined 
data 
end 

回答

0

1:console.log('o = ' + o)是同步代碼,因此它的回調函數之前運行f您傳遞給執行異步的streamToString。所以當時間console.log('o = ' + o)勝過,f函數尚未執行,這就是爲什麼o未定義。只需在回調函數f內部移動console.log即可獲得您想要的內容。

const f = (str) => { 
    o = JSON.parse(str); 
    console.log('o = ' + o); 
} 

2:readable在整個過程中被髮射兩次,read發射只有一次,看到更多細節here