结合Promise和EventEmitter

问题描述 投票:0回答:3

我创建了这个“简单模式”,适用于组合PromiseEventEmitter(与nodejs)。

但是:我想知道是否有更好的方式进球?

const { EventEmitter } = require('events');
const fs = require('fs');

function doSomething(parameters) {
  const emitter = new EventEmitter();

  const promise = new Promise((resolve, reject) => {
    // DO DIRTY JOB
    fs.readdir(parameters.directory, (err, files) => {
      if (err) {
        reject(err);
        return;
      }
      files.forEach(file => emitter.emit('update-event', file));
      resolve(`I'm done: ${parameters.param} world`);
    });
  });
  return { promise, emitter };
}

const work = doSomething({ param: 'hello', directory: './' });
work.emitter.on('update-event', data => console.log(`Update ${data}`));
work.promise.then(console.log).catch(console.error);

我在想:

doSomething(...).on(...).then(...)

但我无法弄清楚这是怎么做到的。

node.js ecmascript-6 promise eventemitter
3个回答
0
投票

不,您不应该在一个对象中组合事件发射器和承诺。单独返回,就像你一样,很好。

当然,在您的特定示例中,根本没有理由使用事件发射器。无论如何,它只会在承诺实现时触发。更简单:

const fs = require('fs');
function doSomething(parameters) {
  return new Promise((resolve, reject) => {
    // DO DIRTY JOB
    fs.readdir(parameters.directory, (err, files) => {
      if (err) reject(err);
      else resolve(Object.assign(files, parameters));
    });
  });
}

doSomething({ param: 'hello', directory: './' }).then(files => {
  for (const data of files) {
    console.log(`Update ${data}`)
  }
  return `I'm done: ${files.param} world`;
}).then(console.log, console.error);

0
投票

我建议这样:

import EventPromised from "event-promised";

function doSomething(parameters) {
    return new EventPromised((resolve, reject, emit) => {
        fs.readdir(parameters.directory, (err, files) => {
            if (err) {
                reject(err);
                return;
            }
            files.forEach(file => emit('update-event', file));
            resolve(`I'm done: ${parameters.param} world`);
        });
    });
}
doSomething({ param: 'hello', directory: './' })
    .on('update-event', data => console.log(`Update ${data}`))
    .then(console.log)
    .catch(console.error);

0
投票

Node.js为此构建了一个函数:require('events').once函数!这里是PR

它已经与Node [v11.13](https://nodejs.org/en/blog/release/v11.13.0/)一起发布

示例用法(来自docs):

const { once, EventEmitter } = require('events');
async function run() {
  const ee = new EventEmitter();
  process.nextTick(() => {
    ee.emit('myevent', 42);
  });
  const [value] = await once(ee, 'myevent');
  console.log(value); // 42

  const err = new Error('kaboom');
  process.nextTick(() => {
    ee.emit('error', err);
  });

  try {
    await once(ee, 'myevent');
  } catch (err) {
    console.log('error happened', err);
  }
}

run();
© www.soinside.com 2019 - 2024. All rights reserved.