本文探討利用原生機(jī)制,來(lái)最快速簡(jiǎn)單的實(shí)現(xiàn)異步事件流。這個(gè)傻瓜化的宗旨,是來(lái)自要面對(duì)的很實(shí)際的問(wèn)題:
事件1 → 事件2 → 事件3 → 事件4 → 事件5 → 事件6 → ...
運(yùn)行任務(wù)1,當(dāng)任務(wù)1完成時(shí)觸發(fā)事件2運(yùn)行任務(wù)2,當(dāng)任務(wù)2完成時(shí)觸發(fā)事件3運(yùn)行任務(wù)3,...
為了說(shuō)明所采用的方式,使用一個(gè)很家常的任務(wù)示例:
→ 'open' 打開(kāi)
/home/xiaoming/myread.txt
文件,獲取文件描述符fd
→ 'read' 通過(guò)
fd
,讀取該文件內(nèi)最多90個(gè)字節(jié)的字符,寫(xiě)入到緩沖區(qū)buffer
→ 'write' 向緩沖區(qū)
buffer
追加1234567890
字符串,通過(guò)fd
,寫(xiě)回文件100個(gè)字符(覆蓋)→ 'close' 關(guān)閉文件描述符
fd
→ 'error' 期間發(fā)生錯(cuò)誤,打印錯(cuò)誤
→ 'done' 全部完成,打印'Open Read Write Close ok.'
以上每個(gè)任務(wù)都是異步的,上一個(gè)完成運(yùn)行下一個(gè)。
以下是源代碼,不言自明。
- 為了舉例方便,這部分代碼并不算完整,比如字節(jié)讀寫(xiě)檢查,錯(cuò)誤釋放fd...并未加入
- 使用這個(gè)原生方式,可以使你最快速的上手異步事件編程
-
new (require('events').EventEmitter)()
可以創(chuàng)建一個(gè)nodejs
事件對(duì)象,擁有on, emit等事件管理方法,詳細(xì)內(nèi)容可以查看文檔 on(事件類型, callback)
emit(事件類型, 參數(shù)1, 參數(shù)2, 參數(shù)3, ...)
-
Buffer
是nodejs讀寫(xiě)數(shù)據(jù)的內(nèi)存緩沖區(qū)的一個(gè)抽象,一種表示方式 - 緩沖區(qū)?向操作系統(tǒng)內(nèi)存申請(qǐng)一片區(qū)域,用來(lái)存放數(shù)據(jù),每隔一段時(shí)間,或者強(qiáng)制調(diào)用系統(tǒng)fsync(),將內(nèi)存中的數(shù)據(jù)寫(xiě)到磁盤(pán)
var myemitter = new (require('events').EventEmitter)(),
fs = require('fs'),
filepath = '/home/xiaoming/myread.txt',
buflen = 100,
buffer = new Buffer(buflen);
myemitter
.on('open', function () {
fs.open(filepath, 'a+', function (err, fd) {
if (err)
myemitter.emit('error', 'open', err);
else
myemitter.emit('read', fd);
});
})
.on('read', function (fd) {
fs.read(fd, buffer, 0, buflen - 10, 0, function (err, bytesRead, buffer) {
if (err)
myemitter.emit('error', 'read', err);
else
myemitter.emit('write', fd);
});
})
.on('write', function (fd) {
buffer.write('1234567890', buflen - 10);
fs.write(fd, buffer, 0, buflen, 0, function (err, written, buffer) {
if (err)
myemitter.emit('error', 'write', err);
else
myemitter.emit('close', fd);
});
})
.on('close', function (fd) {
fs.close(fd, function (err) {
if (err)
myemitter.emit('error', 'close', err);
else
myemitter.emit('done');
})
})
.on('error', function (type, err) {
console.log('Has some error. type: "%s", error: %j.', type, err);
})
.on('done', function () {
console.log('Open Read Write Close ok.');
})
.emit('open')
;