一个叫木头,一个叫马尾

发现一个有趣的方法:events.once

作为一个爱逛推特的人,经常能从别人的推文中发现好东西。之前有几篇文章也是受推文启发所写:

今天谈谈另一个发现: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 the EventEmitter emits the given event or that is rejected when the EventEmitter emits 'error'. The Promise 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);
}

是不是舒服多了?

相关推荐