本文探讨利用原生机制,来最快速简单的实现异步事件流。这个傻瓜化的宗旨,是来自要面对的很实际的问题:
事件1 → 事件2 → 事件3 → 事件4 → 事件5 → 事件6 → ...
运行任务1,当任务1完成时触发事件2运行任务2,当任务2完成时触发事件3运行任务3,...
为了说明所采用的方式,使用一个很家常的任务示例:
→ ‘open’ 打开
/home/xiaoming/myread.txt
文件,获取文件描述符fd
→ ‘read’ 通过
fd
,读取该文件内最多90个字节的字符,写入到缓冲区buffer
→ ‘write’ 向缓冲区
buffer
追加1234567890
字符串,通过fd
,写回文件100个字符(覆盖)→ ‘close’ 关闭文件描述符
fd
→ ‘error’ 期间发生错误,打印错误
→ ‘done’ 全部完成,打印’Open Read Write Close ok.’
以上每个任务都是异步的,上一个完成运行下一个。
以下是源代码,不言自明。
- 为了举例方便,这部分代码并不算完整,比如字节读写检查,错误释放fd…并未加入
- 使用这个原生方式,可以使你最快速的上手异步事件编程
-
new (require('events').EventEmitter)()
可以创建一个nodejs
事件对象,拥有on, emit等事件管理方法,详细内容可以查看文档 on(事件类型, callback)
emit(事件类型, 参数1, 参数2, 参数3, ...)
-
Buffer
是nodejs读写数据的内存缓冲区的一个抽象,一种表示方式 - 缓冲区?向操作系统内存申请一片区域,用来存放数据,每隔一段时间,或者强制调用系统fsync(),将内存中的数据写到磁盘
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')
;