迭代Promise迭代器

时间:2016-04-01 16:56:23

标签: javascript promise

我开发了一个客户端库,它公开了一个名为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')库来构建非递归解决方案?我对非递归方法感兴趣的原因是,如果要迭代的条目数太大,就要避免爆炸。

干杯, 盖尔德

2 个答案:

答案 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
}

read more about it here

否则,您可以使用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
}