作为一个爱逛推特的人,经常能从别人的推文中发现好东西。之前有几篇文章也是受推文启发所写:
今天谈谈另一个发现:events
模块中的 once
函数。
推文下面的评论者是Node.js大神,既然连他都说了这个方法用的很多,我就更有兴趣了解下去了。
来自官方文档(https://nodejs.org/api/events.html#events_events_once_emitter_name):
events.once(emitter, name)
Creates a
Promise
that is fulfilled when theEventEmitter
emits the given event or that is rejected when theEventEmitter
emits'error'
. ThePromise
will resolve with an array of all the arguments emitted to the given event.
大意是该方法会返回一个 Promise
, 当监控的 EventEmitter
对象发布了给定name
的事件后,Promise
变成 resolved,且收到的参数是发布事件时传递的参数(以数组形式);而当EventEmitter
对象发布的是'error'
事件时,Promise
变成 rejected,收到的参数也是发布事件时传递的参数(以数组形式)。
官方给的例子也比较容易理解,我加了注释:
// 引入需要的方法
const { once, EventEmitter } = require('events');
async function run() {
const ee = new EventEmitter();
process.nextTick(() => {
// 异步发布 'myevent' 事件
ee.emit('myevent', 42);
});
// 监听 'myevent' 事件
const [value] = await once(ee, 'myevent');
// 打印 42
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
// 异步发布 'error' 事件
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
// 因为发布了 'error' 事件,所以要在这里的捕获reject异常
// 打印 error happened Error: kaboom
console.log('error happened', err);
}
}
run();
官方例子中的代码是为了方便理解而刻意制造的,有实际生活中的例子吗?
我想到了一个。
我们经常会需要将一个 Readable Stream
的内容写入到 Writable Stream
,并在写入完成(此时会发布 'finish'
事件)或写入失败时(发布'error'
事件)提供进一步的处理逻辑。
如果不知道 events.once
的存在,我们的代码只能利用 callback
回调来处理:
writableStream.on('finish',()=>{
// 成功回调
});
writableStream.on('error',()=>{
// 失败回调
});
而有了 events.once
, 我们便可以用上更直接且易读的 async/await
语法了:
try {
await once(writableString, "finish");
console.log("操作完成");
} catch (e) {
console.log("操作出错: ", e);
}
是不是舒服多了?
async/await
及Promise
:关于Promise和Async/Await你可能不知道的事