How to convert Node.js async streaming callback into an async generator?

前端 未结 3 515
猫巷女王i
猫巷女王i 2021-01-14 11:10

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

3条回答
  •  清酒与你
    2021-01-14 11:41

    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 deferreds (you're never rejecting 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;
        }
    }
    

提交回复
热议问题