Asyn c функции в событии - PullRequest
1 голос
/ 19 марта 2020

Я пытался исправить это в последние дни безуспешно. Я довольно новичок в ноде и асинхронной / син c концепции и, очевидно, мне чего-то не хватает.

Мне нужно запустить al oop один за другим (асин c) внутри событие. Это l oop взаимодействует с базой данных и занимает некоторое время, чтобы быть законченным. Я приложил все усилия с помощью генератора событий и setImmediate (), но все еще получаю функции processMessage и storeMessage syn c. Пожалуйста, посмотрите:

const EventEmitter  = require('events')
const emitter = new EventEmitter()

msg.once('body', stream => {
    emitter.on('done',() => {
        try {
            setImmediate(async ()=>{  // <-- Here I'm trying to queue async the funtion
                await emailService.processMessage(stream);
            })
        } catch(err) {
            helper.logger.error('Problem stockpiling mails to be processed');
        }
    });
});

Затем я вызываю это, когда MSG закончил

f.once('end', function() {
    emitter.emit('done');
});

Я не знаю, находится ли проблема внутри функции, которую я вызываю в setImmediate, так Я оставлю их ниже.

exports.processMessage = async (stream) => {
    /// ...
    await storeMessage(parsed);
    /// ...
}

async function storeMessage (parsed){
    // Some async database interaction
}

1 Ответ

2 голосов
/ 19 марта 2020
Функции

Asyn c работают до достижения значения await, затем они останавливаются и другие функции могут работать. Таким образом, если вы дважды вызываете функцию asyn c, она будет работать «параллельно»:

async function task(id) {
  console.log("before " + id);
  await undefined;
  console.log("after " + id);
}

task(1);
task(2);

Теперь обычным решением будет await различных задач в одной асин c функции, чтобы они выполнялись друг за другом:

 await task(1);
 await task(2);

К сожалению, в вашем случае emitter.on('done',() => { может запускаться несколько раз, в том числе и во время выполнения задачи², поэтому работать с ней будет не так просто. Поэтому мы должны использовать обещания, чтобы связать асин c функции между несколькими обратными вызовами:

 let done = Promise.resolve();

 emitter.on('done',() => {
   done = done.then(async function() {
      // ...
   });
  });

², насколько я вижу. Хотя для вашего варианта использования могут быть более элегантные решения.

...