You can do that even simpler, see e.g. ecmascript 6 - Pausing javascript async function until user action - Stack Overflow :
EventTarget.prototype.listenForEvent = function(type) {
return new Promise(resolve => {
element.addEventListener(type, resolve, {once: true});
});
};
That's probably a bad idea. An async iterator runs only as fast as it is consumed, but events fire at any rate. It would be quite error-prone to write code like
for await (const event of document.body.streamEvents("scroll")) {
await delay(50);
console.log("Debounced scrolling: ", event);
}
console.log("Done"); // dead code?
since the async iterator would not be able to handle the backpressure. Should it just drop events? Should it buffer them? Neither is really desirable.
Using for await
leads to users writing sequential code, addEventListener
allows writing properly concurrent asynchronous code.
Btw, there is (do I need to say: was?) GitHub - tc39/proposal-observable: Observables for ECMAScript which proposed a proper abstraction for push-based event sources.