深入理解Node中可讀流和可寫流

2021-09-14 04:05:24 字數 3163 閱讀 6176

這個字進入我腦海我第一時間想到的是一句詩,抽刀斷水水更流,舉杯消愁...額,今天的主角是流。不好意思差點跑題了,嗯,流是乙個抽象介面,被 node 中的很多物件所實現。比如http伺服器request和response物件都是流。本人最近研究node,特意記下,分享一下。

對於流,官方文件是這樣描述的:

流(stream)在 node.js 中是處理流資料的抽象介面(abstract inte***ce)
node.js 中有四種基本的流型別:

今天主要分享的是node可讀流和可寫流

先上個流程圖讓大家直觀了解整個流程

可寫流的模擬實現:

let eventemitter = require('events');

class writestream extends eventemitter

open()

return this.emit('error', err);

}this.fd = fd;

this.emit('open');

});}

//如果底層已經在寫入資料的話,則必須當前要寫入資料放在緩衝區裡

write(chunk, encoding, cb) );

} else

return ret;

}clearbuffer() else

}_write(chunk, encoding, cb)

fs.write(this.fd,chunk,0,chunk.length,this.pos,(err,byteswritten)=>

}this.pos += byteswritten;

//寫入多少字母,快取區減少多少位元組

this.length -= byteswritten;

cb && cb();})}

destroy() )

}}module.exports = writestream;

可讀流事實上工作在下面兩種模式之一:flowing 和 paused

flowing 流動模式

流動模式比較簡單,**實現如下:

let eventemitter = require('events');

let fs = require('fs');

class readstream extends eventemitter

});}

read()

let howmuchtoread = this.end?math.min(this.end - this.pos + 1,this.highwatermark):this.highwatermark;

並不是快取區

console.log('howmuchtoread',howmuchtoread);

fs.read(this.fd,this.buffer,0,howmuchtoread,this.pos,(err,bytes)=>

if(bytes)else

}else})}

endfn()

open()

}this.fd = fd;

this.emit('open');})}

destroy());

}pipe(dest)

});dest.on('drain',()=>);

}//可讀流會進入流動模式,當暫停的時候,

pause()

resume()

}module.exports = readstream;

paused 暫停模式:
暫停模式邏輯有點複雜, 畫了一張圖梳理一下
_read 方法是把資料存在快取區中,因為是非同步 的,流是通過readable事件來通知消耗方的。

說明一下,流中維護了乙個快取,當快取中的資料足夠多時,呼叫read()不會引起_read()的呼叫,即不需要向底層請求資料。state.highwatermark是給快取大小設定的乙個上限閾值。如果取走n個資料後,快取中保有的資料不足這個量,便會從底層取一次資料

暫停模式**模擬實現:

let fs = require('fs');

let eventemitter = require('events');

class readstream extends eventemitter

});this.on('newlistener', (type) =>

if (type == 'readable')

});this.open();

}open()

}this.fd = fd;

this.emit('open');

});}

read(n)

n = parseint(n, 10);

if (n != n)

if (this.length == 0)

this.needreadable = true;

let ret;

if (0 < n < this.length) }}

if (this.encoding) ret = ret.tostring(this.encoding);

}//資料存快取區中

let _read = () =>

let data;

if (bytesread > 0)

this.emit('end');

} else

}} else

return this.emit('end');}})

}if (this.length == 0 || (this.length < this.highwatermark))

return ret;

}destroy() );

}pause()

resume()

pipe(dest) );

dest.on('drain', () => );

this.on('end', () => );

}}module.exports = readstream;

小弟我能力有限,歡迎各位大神指點,謝謝~

深入理解lua中的 和

在研究cocos2d lua引擎原始碼的時候,看到framework cc components component.lua中有這段 function component exportmethods methods self.exportedmethods methods local target ...

深入理解Objective c中 class的含義

原文 來自 在objective c中,當乙個類需要引用另乙個類,即建立復合關係的時候,需要在類的標頭檔案中建立被引用類的指標。如 car.h 實現類我們先省略,如果你直接這麼編譯,編譯器會報錯,告訴你它不知道tire和engine是什麼。這時候有兩個選擇,乙個是import這兩個被引用類的標頭檔案...

深入理解Objective c中 class的含義

在objective c中,當乙個類需要引用另乙個類,即建立復合關係的時候,需要在類的標頭檔案中建立被引用類的指標。如 car.h 實現類我們先省略,如果你直接這麼編譯,編譯器會報錯,告訴你它不知道tire和engine是什麼。這時候有兩個選擇,乙個是import這兩個被引用類的標頭檔案,另乙個是使...