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

前端 未结 3 551
猫巷女王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:37

    Would it work if there will be typescript solution?

    It should handle condition when callback is called faster then promise is resolved a couple of times. Callback can be a method that has this signature callback(error, result, index) It is set to finish when callback is called with no arguments. Usage:

    asAsyncOf(this.storage, this.storage.each);
    

    Solution:

    function asAsyncOf(c, fn: { (a: T1, a1: T2, a2: T3, a3: T4, cb: { (err?, res?: Y, index?: number): boolean }): void }, a: T1, a1: T2, a2: T3, a3: T4): AsyncGenerator
    function asAsyncOf(c, fn: { (a: T1, a1: T2, a2: T3, cb: { (err?, res?: Y, index?: number): boolean }): void }, a: T1, a1: T2, a3: T3): AsyncGenerator
    function asAsyncOf(c, fn: { (a: T1, a1: T2, cb: {(err?, res?: Y, index?: number): boolean}): void}, a: T1, a1: T2): AsyncGenerator
    function asAsyncOf(c, fn: { (a: T, cb: { (err?, res?: Y, index?: number): boolean }): void }, a: T): AsyncGenerator
    function asAsyncOf(c, fn: { (cb: {(err?, res?: Y, index?: number): boolean}): void}): AsyncGenerator
    async function* asAsyncOf(context, fn, ...args) {
        let next = (result?) => { };
        let fail = (err) => { };
        let finish = {};
        const items = [];
        let started = true;
        try {
            fn.apply(context, [...args, function (err, result, index) {
                const nextArgs = [].slice.call(arguments, 0);
                if (nextArgs.length === 0) {
                    started = false;
                    next(finish);
                    return true;
                }
                if (err) {
                    fail(err);
                    return true;
                }
                items.push(result);
                next(result);
            }]);
        } catch (ex) {
            fail(ex);
        }
        while (true) {
            const promise = started ? new Promise((resolve, error) => {
                next = resolve;
                fail = error;
            }) : Promise.resolve(finish);
            const record = await promise;
            if (record === finish) {
                while (items.length) {
                    const item = items.shift();
                    yield item;
                }
                return;
            }
            while (items.length) {
                const item = items.shift();
                yield item;
            }
        }
    }
    export { asAsyncOf };
    

提交回复
热议问题