可以进行"滚动"请求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();

希望有人能指出如何实现这样的目标。谢谢!
答案 0 :(得分:2)
不,这不可能实现。生成器和for … of
是同步的。当然,您可以产生承诺,但这并不能为您带来任何好处 - 而且您最好使用async
/ await
语法。
但是,您想要查看async iteration proposal。