1. 通過(guò)流讀取數(shù)據(jù)
用Readable創(chuàng)建對(duì)象readable后俏蛮,便得到了一個(gè)可讀流。
如果實(shí)現(xiàn)_read方法读恃,就將流連接到一個(gè)底層數(shù)據(jù)源愕鼓。
流通過(guò)調(diào)用_read向底層請(qǐng)求數(shù)據(jù)雷滚,底層再調(diào)用流的push方法將需要的數(shù)據(jù)傳遞過(guò)來(lái)需曾。
當(dāng)readable連接了數(shù)據(jù)源后,下游便可以調(diào)用readable.read(n)向流請(qǐng)求數(shù)據(jù)祈远,同時(shí)監(jiān)聽(tīng)readable的data事件來(lái)接收取到的數(shù)據(jù)呆万。
2. read(fs:2060,372)
read方法中的邏輯可用下圖表示
3. push(fs:2108,197)
- 消耗方調(diào)用read(n)促使流輸出數(shù)據(jù),而流通過(guò)_read()使底層調(diào)用push方法將數(shù)據(jù)傳給流车份。
- 如果流在流動(dòng)模式下(state.flowing為true)輸出數(shù)據(jù)谋减,數(shù)據(jù)會(huì)自發(fā)地通過(guò)data事件輸出,不需要消耗方反復(fù)調(diào)用read(n)扫沼。(fs:268)
- 如果調(diào)用push方法時(shí)緩存為空出爹,則當(dāng)前數(shù)據(jù)即為下一個(gè)需要的數(shù)據(jù)。這個(gè)數(shù)據(jù)可能先添加到緩存中缎除,也可能直接輸出。
- 執(zhí)行read方法時(shí)器罐,在調(diào)用_read后梢为,如果從緩存中取到了數(shù)據(jù),就以data事件輸出(fs:482)轰坊。
- 所以铸董,如果_read異步調(diào)用push時(shí)發(fā)現(xiàn)緩存為空,則意味著當(dāng)前數(shù)據(jù)是下一個(gè)需要的數(shù)據(jù)肴沫,且不會(huì)被read方法輸出粟害,應(yīng)當(dāng)在push方法中立即以data事件輸出(_stream_readable:268)。
4. end事件
- 在調(diào)用完_read()后颤芬,read(n)會(huì)試著從緩存中取數(shù)據(jù)(_stream_readable:459)我磁。
- 如果_read()是異步調(diào)用push方法的孽文,則此時(shí)緩存中的數(shù)據(jù)量不會(huì)增多,容易出現(xiàn)數(shù)據(jù)量不夠的現(xiàn)象(_stream_readable:463)夺艰。
- 如果read(n)的返回值為null,說(shuō)明這次未能從緩存中取出所需量的數(shù)據(jù)沉衣。 此時(shí)郁副,消耗方需要等待新的數(shù)據(jù)到達(dá)后再次嘗試調(diào)用read方法(_stream_readable:280)。
- 在數(shù)據(jù)到達(dá)后豌习,流是通過(guò)readable事件來(lái)通知消耗方的(_stream_readable:280)存谎。
- 在此種情況下,push方法如果立即輸出數(shù)據(jù)肥隆,接收方直接監(jiān)聽(tīng)data事件即可既荚,否則數(shù)據(jù)被添加到緩存中,需要觸發(fā)readable事件(_stream_readable:280)
- 消耗方必須監(jiān)聽(tīng)這個(gè)readable事件栋艳,再調(diào)用read方法取得數(shù)據(jù)恰聘。
5. doRead
- 流中維護(hù)了一個(gè)緩存,當(dāng)緩存中的數(shù)據(jù)足夠多時(shí)吸占,調(diào)用read()不會(huì)引起_read()的調(diào)用晴叨,即不需要向底層請(qǐng)求數(shù)據(jù)。
- 用doRead來(lái)表示read(n)是否需要向底層取數(shù)據(jù)(_stream_readable:431)
- state.reading標(biāo)志上次從底層取數(shù)據(jù)的操作是否已完成矾屯。一旦push方法被調(diào)用兼蕊,就會(huì)設(shè)置為false,表示此次_read()結(jié)束件蚕。
- state.highWaterMark是給緩存大小設(shè)置的一個(gè)上限閾值孙技。
- 如果取走n個(gè)數(shù)據(jù)后,緩存中保有的數(shù)據(jù)不足這個(gè)量排作,便會(huì)從底層取一次數(shù)據(jù)(_stream_readable:431)牵啦。
6. howMuchToRead
用read(n)去取n個(gè)數(shù)據(jù)時(shí),m = howMuchToRead(n)是將從緩存中實(shí)際獲取的數(shù)據(jù)量(_stream_readable:346)纽绍。
可讀流是獲取底層數(shù)據(jù)的工具蕾久,消耗方通過(guò)調(diào)用read方法向流請(qǐng)求數(shù)據(jù),流再?gòu)木彺嬷袑?shù)據(jù)返回拌夏,或以data事件輸出僧著。
如果緩存中數(shù)據(jù)不夠,便會(huì)調(diào)用_read方法去底層取數(shù)據(jù)障簿。
該方法在拿到底層數(shù)據(jù)后盹愚,調(diào)用push方法將數(shù)據(jù)交由流處理(立即輸出或存入緩存)。
可以結(jié)合readable事件和read方法來(lái)將數(shù)據(jù)全部消耗站故,這是暫停模式的消耗方法皆怕。
read(0) 只是填充緩存區(qū)毅舆,并不真正讀取
read() 如果處于流動(dòng)模式,并且緩存區(qū)大小不為空愈腾,則返回緩存區(qū)第一個(gè)buffer的長(zhǎng)度憋活,否則讀取整個(gè)緩存 如果讀到了數(shù)據(jù)沒(méi)有返回值,但是會(huì)發(fā)射data事件,數(shù)據(jù)也能取到,也就是用來(lái)清空緩存區(qū)