我开发了一个客户端库,它公开了一个名为iterator()
的方法。此方法返回使用require('promise')
库创建的Promise实例,该实例使用迭代器对象完成。
此对象包含一个名为next()
的方法,该方法返回一个Promise,它使用如下复杂对象完成:{done: [true|false], key: _, value: _}
虽然iterator()
可能预先获取某些元素,但next()
需要返回Promise,以防它导致远程调用。
现在,假设用户想要迭代所有元素,直到next()
返回的Promise返回包含done: true
的对象。
我已经设法使用以下递归方法实现了这一点(我最初在此answer中找到了此解决方案):
var iterate = client.iterator();
iterateTeams.then(function(it) {
function loop(promise, fn) {
// Simple recursive loop over iterator's next() call
return promise.then(fn).then(function (entry) {
return !entry.done ? loop(it.next(), fn) : entry;
});
}
return loop(it.next(), function (entry) {
console.log('entry is: ' + entry);
return entry;
});
});
问题是,是否可以使用require('promise')
库来构建非递归解决方案?我对非递归方法感兴趣的原因是,如果要迭代的条目数太大,就要避免爆炸。
干杯, 盖尔德
答案 0 :(得分:2)
不要害怕。不要害怕。异步"递归" (有时被称为https://jira.spring.io/browse/INT)不会增加调用堆栈,它很像尾递归。你不会得到一个stackoverflow异常。我对非递归方法感兴趣的原因是,如果要迭代的条目数太大,就要避免爆炸
如果合理地实施了promise库,这甚至不会增加内存 - 有关详细信息,请参阅pseudo-recursion。
答案 1 :(得分:1)
没有新语法或库 - 通常没有。
好吧,如果你正在使用babel,你可以使用ES2018(:P)异步迭代:
for await (const team of iterateTeams) {
// do something with team
}
否则,您可以使用ES2016异步/等待语法的生成器:
for(var it = iterateTeams(); !done; ({done, value}) = await it.next()) {
// work with value
}
或者今天可用的ES2015生成器语法和通过bluebird的泵:
// inside a Promise.corutine
for(var it = iterateTeams(); !done; ({done, value}) = yield it.next()) {
// work with value
}