這個字進入我腦海我第一時間想到的是一句詩,抽刀斷水水更流,舉杯消愁...額,今天的主角是流。不好意思差點跑題了,嗯,流是乙個抽象介面,被 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這兩個被引用類的標頭檔案,另乙個是使...