I have a function that streams data in batches via a callback.
Each batch will await the callback function before fetching another batch and the entire function retu
No, I don't think there's a way to implement this transformation in a way that's easy to understand and easy to follow. However, I would recommend to drop the deferred
s (you're never reject
ing anyway) and just use the promise constructor. Also I'd rather implement an asynchronous generator right away.
function queue() {
let resolve = () => {};
const q = {
put() {
resolve();
q.promise = new Promise(r => { resolve = r; });
},
promise: null,
}
q.put(); // generate first promise
return q;
}
function toAsyncIterator(callbackStream) {
const query = queue();
const result = queue();
const end = callbackStream(batch => {
result.put(batch);
return query.promise;
}).then(value => ({value, done: true}));
end.catch(e => void e); // prevent unhandled promise rejection warnings
return {
[Symbol.asyncIterator]() { return this; },
next(x) {
query.put(x);
return Promise.race([
end,
result.promise.then(value => ({value, done:false})
]);
}
}
}
async function* batchToAsyncIterator(batchCallbackStream) {
for await (const batch of toAsyncIterator(batchCallbackStream)) {
// for (const val of batch) yield val;
// or simpler:
yield* batch;
}
}