如何在事件处理程序中实现异步/等待?

时间:2019-12-18 14:08:53

标签: node.js es6-promise eventemitter

我在实现事件处理程序内部的等待时遇到问题。由于某种原因,事件处理程序在启动新进程之前不会等待第一个进程完成。为什么这种奇怪的行为如此?

const { EventEmitter } = require("events");

let alreadyRunning = false;

const sampleEventHandler = new EventEmitter();
sampleEventHandler.on("data", async (message) => {
  await heavyProcess(message);
});

async function heavyProcess(message) {
  console.log("New message: ", message);
  console.log("already running?: ", alreadyRunning);
  if (alreadyRunning) {
    console.log("Why doesn't it await for first task to complete fully before entering here?");
  }

  const rand = Math.random() * 1000;
  // set var here
  alreadyRunning = true;
  await sleep(rand);
  // unset here
  alreadyRunning = false;
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// Emit event 5 times
for (let i = 0; i < 5; i++) {
  sampleEventHandler.emit("data", i);
}

2 个答案:

答案 0 :(得分:0)

编辑: 之所以不丢弃它,是因为您仅在做console.log。在其下添加退货。

async function heavyProcess(message) {
  console.log("New message: ", message);
  console.log("already running?: ", alreadyRunning);
  if (alreadyRunning) {
    console.log("Why doesn't it await for first task to complete fully before entering here?");
     return // Actually stop executing
  }

  const rand = Math.random() * 1000;
  // set var here
  alreadyRunning = true;
  await sleep(rand);
  // unset here
  alreadyRunning = false;
}

编辑2: 注释如下:OP的必要行为是,HeavyProcess应该只发生一次,并且只有在进程完成后才开始一个新进程。

每个事件现在都在启动一个新的heavyProcess,因为等待只是在等待结果,它不会阻塞。

您必须在事件中自行引入阻止功能(或使用RXJS exhaustMap或类似功能)。

let isProcessing = false;

sampleEventHandler.on("data", (message) => {
  if (isProcessing) { return; }
  isProcessing = true;
  const resetProcessing = () => isProcessing = false
  heavyProcess(message).then(resetProcessing, resetProcessing); // Reset of both complete and error

答案 1 :(得分:0)

您需要启用heavyProcess函数才能成功使用await:

function heavyProcess(message) {
    return new Promise( async (resolve, reject) => {
        console.log("New message: ", message);
        console.log("already running?: ", alreadyRunning);
        if (alreadyRunning) {
            console.log("Why doesn't it await for first task to complete fully before entering here?");
        }

        const rand = Math.random() * 1000;
        // set var here
        alreadyRunning = true;
        await sleep(rand);
        // unset here
        alreadyRunning = false;
        resolve('Done');
    });
}