So, what about adding some API functions:
s.nextEvent(eventName) - basically returns new Promise(resolve => s.once(eventName, (...args) => resolve(args))). Not a huge fan of the name nextEvent, but it's an idea (also thought of waitFor, onceAsync, etc.). Also considered having s.once(eventName) return a Promise that resolves when we receive eventName... but then I think we'd need a corresponding s.on(eventName) that returns an AsyncIterator, but I don't like that idea (see s.iterate below)
s.iterate(eventName) - sets up an event handler for eventName on the channel and returns an AsyncIterator. When the user calls next(), the next value is retrieved. I personally don't like this API very much because events can be received and buffered without being immediately consumed (i.e. next() can be called much later after receiving). It defers event processing until event consumption, which feels bad to me... and we resort to buffering when normally buffering is not needed. One idea I have is that we can buffer exactly one value. If it is not immediately consumed by the next run of the event loop, then we remove the event handler and the AsyncIterator returns a final error.
- Event handlers could be async generator functions or return AsyncIterators. In this case, the
.request() method would return a Promise that resolves to an AsyncIterator. Calling .next(value) on this would pass the value to the remote end, much like a request and the return value of .next(...) is the value received by the AsyncIterator. If this works, even Go event handlers could return a channel as its data, and values are read from the channel and forwarded to the remote end until the channel closes.
So, what about adding some API functions:
s.nextEvent(eventName)- basically returnsnew Promise(resolve => s.once(eventName, (...args) => resolve(args))). Not a huge fan of the namenextEvent, but it's an idea (also thought ofwaitFor,onceAsync, etc.). Also considered havings.once(eventName)return a Promise that resolves when we receiveeventName... but then I think we'd need a correspondings.on(eventName)that returns an AsyncIterator, but I don't like that idea (sees.iteratebelow)s.iterate(eventName)- sets up an event handler foreventNameon the channel and returns an AsyncIterator. When the user callsnext(), the next value is retrieved. I personally don't like this API very much because events can be received and buffered without being immediately consumed (i.e.next()can be called much later after receiving). It defers event processing until event consumption, which feels bad to me... and we resort to buffering when normally buffering is not needed. One idea I have is that we can buffer exactly one value. If it is not immediately consumed by the next run of the event loop, then we remove the event handler and the AsyncIterator returns a final error..request()method would return a Promise that resolves to an AsyncIterator. Calling.next(value)on this would pass thevalueto the remote end, much like a request and the return value of.next(...)is the value received by the AsyncIterator. If this works, even Go event handlers could return a channel as its data, and values are read from the channel and forwarded to the remote end until the channel closes.