使用递归生成生成器并且可以很好地使用promises

时间:2017-06-15 01:07:54

标签: javascript node.js recursion ecmascript-6 generator

可以进行"滚动"请求Elasticsearch。它保持光标打开,您可以逐个检索大块数据。

There's some demo code available,它使用回调和递归来继续获取数据,直到我们完成。在我编写的Node应用程序中,我想将每个数据块流式传输到一个zip或在某处写入,然后忘记它并获取一大块新数据。但是在示例中,它们将所有数据存储到一个数组中,这可能导致大量数据的内存问题。

生成器函数非常适合从每个.next()的Elasticsearch获取一些数据,然后在调用另一个.next()之前将其写出来,它将从滚动端点获取一些数据并使用递归

我目前真的很困惑如何实现这一目标。我们必须同步等待promise(Elasticsearch调用)来解析,然后产生响应。但它也需要产生递归函数等。

在用不同的方式尝试了几个小时之后,生成器函数,承诺和递归的混合使我感到困惑。我写了一些类似于我想要实现的简化代码:



console.clear();

// Elasticsearch search call
function searchMockPromise() {
    return new Promise(resolve => {
        setTimeout(() => {
            let response = {};
            response.hits = {
                total: 50,
                hits: [1, 2, 3, 4, 5]
            };
            resolve(response);
        }, 2000);
    });
}

// Elasticsearch scroll call
function scrollMockPromise() {
    return new Promise(resolve => {
        setTimeout(() => {
            let response = {};
            response.hits = {
                total: 50,
                hits: [1, 2, 3, 4, 5]
            };
            resolve(response);
        }, 2000);
    });
}

function* exportGenerator() {
    let count = 0;

    console.log("Executing search call first");
    yield searchMockPromise()
        .then(function* (resp) {
            yield* scrollCallback(resp);
            return resp.hits.hits;
        });

    function* scrollCallback(response) {
        console.log("Executing scroll callback");

        count += response.hits.hits.length;

        if (response.hits.total !== count) {
            console.log("Theres more data to fetch, now make a scroll call");

            yield scrollMockPromise()
                .then(function* (resp) {
                    console.log("It executed a scroll call");
                    yield* scrollCallback(resp);
                    return response.hits.hits;
                });
        }
    }
}

function init() {
    // We just want the generator to return the "response" objects from the callbacks of the Promises...
    // E.g. every part of data we get from the generator, we can inject into a streaming zip or write it somewhere.
    for (let data of exportGenerator()) {
        const promise = yield data;
        const output = yield promise;
        console.log(output);
    }
}
init();




希望有人能指出如何实现这样的目标。谢谢!

1 个答案:

答案 0 :(得分:2)

不,这不可能实现。生成器和for … of是同步的。当然,您可以产生承诺,但这并不能为您带来任何好处 - 而且您最好使用async / await语法。

但是,您想要查看async iteration proposal