我在实现事件处理程序内部的等待时遇到问题。由于某种原因,事件处理程序在启动新进程之前不会等待第一个进程完成。为什么这种奇怪的行为如此?
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);
}
答案 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');
});
}