- From: Ben Lesh <notifications@github.com>
- Date: Wed, 05 Jan 2022 12:11:39 -0800
- To: whatwg/dom <dom@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/dom/issues/1038/1006042750@github.com>
In general, I like this sort of idea. However, I'd caution against it because of the nuance involved with converting something that's entirely push-based (EventTarget) to something that is pull-push based (AsyncIterable). The latter is much more complicated and that complication/nuance is generally lost in async functions with for-await loops. We looked at making RxJS's observable implement `[Symbol.asyncIterator]` but ultimately found it might be more problematic for users than beneficial. It comes down to the fact there are really 4 basic ways (and oodles of others) people will want to deal with observables in a for-await loop, and the fact that the most intuitive one of those ways has a lot of overhead (mental and technical) that people will have a hard time understanding. Ultimately, the team decided not to go ahead with the idea, and instead I [published a library to convert observables to AsyncIterables](https://www.npmjs.com/package/rxjs-for-await). Consider the complexity added even in this simple case: ```ts textInput.addEventListener('input', async (e) => { // this is hit IMMEDIATELY every time the input is changed const data = await getData(textInput.value); render(data); }); // vs for await (const e of textInput.on('input')) { // This is hit IMMEDIATELY the FIRST time the input is changed // however, if the input is changed while `getData` is doing its thing, // then it will not be hit again until `getData` finishes doing its thing. // BUT, if the button is clicked two or three times while `getData` is doing // its thing, THEN you have to wait for each of the previous events to be // processed. // ADDITIONALLY, the state of `textInput.value`, and the rest of the app, // will have changed by the time this is hit in those cases, so you may // end up sending something you're not expecting. const data = await getData(textInput.value); render(data); } ``` In short, while I think this improves the superficial ergonomics of `EventTarget`, ultimately I think it makes the code and the type itself harder to reason about because the underlying type and its interactions are more complex. A pushed based type, like an observable, in likely a better choice for this use-case IMO: https://github.com/whatwg/dom/issues/544 However, I do think that there's some merit to making other things, like `ReadableStream` and the like, into AsyncIterables, as the complexity matches pretty much 1:1. -- Reply to this email directly or view it on GitHub: https://github.com/whatwg/dom/issues/1038#issuecomment-1006042750 You are receiving this because you are subscribed to this thread. Message ID: <whatwg/dom/issues/1038/1006042750@github.com>
Received on Wednesday, 5 January 2022 20:11:52 UTC