【问题标题】:Proper way of using loops in Promises在 Promise 中使用循环的正确方法
【发布时间】:2015-09-01 12:47:03
【问题描述】:

根据这个link(菜鸟错误#2)我不应该在Promises中使用循环,而是Promise.all(iterable)

这真的适用于所有循环吗? Promise.all(iterable) 采用大小为 n 的数组。如果我使用Promise.all(iterable),那么我会得到一个大小为 n 的数组(即 iterable_A)。

如果我想遍历 iterable 并且只想将满足我的条件的某些元素放入另一个 iterable(例如 iterable_B)并想返回 iterable_B 而不是 iterable_A 怎么办?我也应该使用Promise.all()吗?

【问题讨论】:

  • 您可以在 Promise 中使用循环,只要它们不会花费太多时间来执行并且您不会在循环中执行任何异步任务。
  • 啊,是的。这就说得通了。上面链接中的文章对此并不清楚。它给人的印象是所有循环都被承诺禁止。

标签: javascript asynchronous callback promise


【解决方案1】:

我不应该在 Promises 中使用循环

不,相反:你不应该在循环中使用 Promise。

当然这也太笼统了。有时你只需要一个循环结构。您不能做的是忘记收集在循环体中创建的承诺,您可以将其传递给Promise.all,以等待在该循环中启动的所有异步操作。 p>

文章中建议的map method 自然会做到这一点,您只需要return 来自回调的承诺(一如既往)。使用 for/while/.forEach 会更难一些,因为您必须手动将 promise 推送到某个数组中(这不仅丑陋而且容易出错)。

但是,如果您不在循环中处理异步任务,您可以做任何您想做的事情。例如,两者

Promise.all(values.filter(syncPredicate).map(asyncFn))

Promise.all(promises).then((values) => values.filter(syncPredicate))

完全没问题。当你有一个异步过滤谓词时,它确实会变得有点复杂,我建议在这种情况下寻找一个 Promise 实用程序库。

您还必须意识到,从同步循环构造中启动的异步任务将并行运行。如果您打算按顺序运行它们(等待每次迭代),您应该尝试制定循环using a recursive structure

【讨论】:

  • 您认为以下函数是否应该重构?我特别指的是该函数中的回调、延迟和 for 循环:
  • var getAllFooById = function(id){ var dfd = $q.defer(); db.allDocs({include_docs: true}, function(err, response) { if(err) { console.log(err); dfd.reject(err); } else { var fooArray = []; for(var i=0; i < response.total_rows; i++) { if(response.rows[i].doc.type == 'foo' && response.rows[i].doc.id == id) { fooArray.push({bar: response.rows[i].doc._id}); } } dfd.resolve(fooArray); } }); return dfd.promise; };
  • 这是一个新问题吗? answer?我无法真正破译 cmets 中未格式化的代码,但看起来您正在使用 deferred antipattern
  • 抱歉格式化。这是您所说的一个问题:“如果您不在循环内处理异步任务,您可以做任何您想做的事情。”:response 是异步的吗?我应该将for-loop 保持原样还是将其更改为Promise.all()
  • @thadeuszlay:我不知道db.allDocs 是什么,所以我不能肯定地说,但它看起来肯定是异步的。如果不是,您将不必使用延迟。但是,是的,该回调中的for 循环不会做任何异步操作,它只是response 上的同步循环,无需在其中使用Promise.all。但是,您的回调应该只做if (err) dfd.reject(err); else dfd.resolve(response); 而没有别的,所有console.log 和循环的东西都应该放在一个单独的.then() 回调中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 2013-01-17
  • 2012-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多