【问题标题】:How to return value from a syncronous function from asyncronous function invoqued from event emitter?如何从事件发射器调用的同步函数中返回同步函数的值?
【发布时间】:2020-12-18 21:37:09
【问题描述】:

我有同步工作逻辑,我想把它转换成异步事件驱动代码。

如何让 async foo 在事件链的末尾返回回调的承诺值( done() || fail() )?

就像让这个过于简单的例子起作用

async function foo(param){
  eventEmitter.emit('first-event', param);
}

eventEmitter.on('first-event', /*Do something*/);
.
.
.
eventEmitter.on('last-event', (payload) => {
  try{
   /*If no error*/
   eventEmitter.emit('done', payload);
  }catch{
   /*If error*/
   eventEmitter.emit('fail', error);
  }
});

function done(payload){
  return ({payload:payload});
}

function fail(error){
  return ({fail:error});
}

eventEmitter.on('done', payload => done(payload) );

eventEmitter.on('error', error => fail(error) );

如果有人知道它的相关信息,感谢您分享它和您的时间,如有任何错误,我们深表歉意。

【问题讨论】:

  • "我想将其转换为异步事件驱动代码。" - 为什么?您能否发布您的工作同步逻辑,并告诉我们它如何不再满足您的要求?
  • 一般来说,只是use return events.once(eventEmitter, 'done');(并使用'error',而不是'fail'
  • 使用构造函数
  • @Thomas 呃,不是吗?
  • @Bergi "你能发布你的工作同步逻辑,告诉我们它是如何不再满足你的要求的吗?"与需求无关,只是将其转换为发出的事件

标签: javascript node.js asynchronous events async-await


【解决方案1】:

经过大量阅读以下的cmets和链接:

@Bergi 
@TheMaster
@Thomas

我认为我找到了最好的解决方案我希望我没有错,如果我是的话,我希望不要过分要求那些回应的人这样做是为了解决问题而不是仅仅指点出一个错误或不喜欢的东西。

“请给我看代码!” ;)

这是拆分字符串的最愚蠢方法的示例 使用 eventEmitter、async await 和这种方法并且有效!

let event = new(require('events').EventEmitter);

async function split(string) {

  let holder = {};
  let promise = async() => {
    return await (holder.payload || holder.error) ? holder : null;
  }

  event.on('done', data => done(data));

  function done(data) {
    try {
      console.log('Done emitted');
      console.log(`Param: ${data}`);
      holder.payload = data;
    } catch(error) {
      console.log(error);
    }
  }

  event.on('error', error => fail(error));

  function fail(error) {
    try {
      console.log('Fail emitted');
      console.log(`Param: ${error}`);
      holder.error = error;
    } catch(error) {
      console.log(error);
    }
  }

  event.on('split', async(string) => {
    try {
      console.log('Split emitted');
      console.log(`Param : ${string}`);
      const data = string.split(' ');
      event.emit('done', data);
    } catch(error) {
      console.log(error);
      event.emit('error', error);
    }
  });

  try {
    event.emit('split', string);
    return({ payload: await promise().then(data => { return data.payload }) });
  } catch(error) {
    console.log(error);
  }

}

console.clear()
console.log(
  split('Hello world').then(data => {
    console.log('Split done!');
    console.log(data);
  })
);

所以此时 var 'holder' 和 function 'promise' 位于函数“split”的范围内,所有控制台输出为:

Split emitted
Param : Hello world
Done emitted
Param: Hello,world
Promise { <pending> }
Split done!
{ payload: [ 'Hello', 'world' ] }

重点是说明可以有 n 个异步事件、回调和承诺 并且能够在经过 n 个阶段或事件的过程后返回一个值

感谢您的时间,以及任何其他 cmets,对于任何错误,我们深表歉意。

【讨论】:

  • "我想我找到了最好的解决方案" - 不,你没有。除了人为的承诺之外,这段代码没有任何异步。它有效,因为所有事件都是同步发出的。 async function split(string) { return string.split(' '); } 甚至只是 function split(string) { return Promise.resolve(string.split(' ')); } 绝对没有任何收获。
  • @Bergi 感谢您的回答,它很有教育意义,并且包含代码,但其中的事件在哪里?关键是使用 n 个事件对一个变量或参数做 n 个事情,并从最后一个事件返回一个值“如何从事件发射器调用的异步函数从同步函数返回值?”
  • 其中没有任何事件,这就是重点。你不应该使用它们,它们所做的只是让你的代码更复杂。您同步发出的事件甚至不会使任何事情异步。
【解决方案2】:

如果你必须这样做,promise 构造函数将起作用:

let p = {};
async function foo(param) {
  eventEmitter.emit('first-event', param);
  return await new Promise((res, rej) => (p.res = res) && (p.rej = rej));
}
//...
eventEmitter.on('done', payload => done(payload) && p.res());

eventEmitter.on('error', error => fail(error) && p.rej());

【讨论】:

  • 不,不要那样做。无需导出rejectresolve 函数,只需将on() 调用移动到new Promise 执行程序中即可。
  • @Bergi 有什么反对出口的具体原因吗?如果我把它放进去,它可能看起来像回调地狱,如果代码增长。
  • Using the Promise constructor as supposed,不创建an unnecessary deferred,由于p 的可变性而减少了脆弱性,全局范围内的变量更少,更好地控制谁可以解决承诺(无法访问p ),并且通常更简单的代码和更好的错误处理。
  • 事实上,我什至会争辩说您的代码已损坏,因为如果多次调用foo(),它将无法工作,但考虑到eventEmitter 的设置方式,它可能无论如何都无法工作由 OP 提供。
  • 也不,我们使用承诺来避免回调地狱:如果代码增长,它将在new Promise之外增长,在await之后 - 这就是全部练习的重点。
猜你喜欢
  • 1970-01-01
  • 2019-02-27
  • 2015-08-24
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 1970-01-01
  • 2019-04-06
相关资源
最近更新 更多