【问题标题】:generators + promises to parallelize N number of items生成器 + 承诺并行化 N 个项目
【发布时间】:2016-12-24 21:27:37
【问题描述】:

挑战:

  1. 我们希望为项目的子项发出 N 个并行 ajax 请求。
  2. 返回后,我们希望按顺序处理它们 (1...N)
  3. 我们不想等待所有承诺返回,但我们希望在它们返回时按顺序处理它们。

例如:

即使 2,3,5 在 1 之前返回,我们应该保留 2,3,5 的结果,在 1 返回时,按顺序处理 1,2,3(并等待 4 在之前返回5)

工具:Q + ES6 生成器

使用占位符变量创建长度为 N-1 的数组

当 N = 3 时的EG:

let [N1,N2,N3] = yield [ Promise1, Promise2, Promise3 ]

//process items sequentially:
   console.log(N1)
   console.log(N2)
   console.log(N3)

但是,填充空变量数组似乎并不奏效,因为引用不知道在哪里可以找到 var 声明

for(var i = 0; i< 3; i++) {
   res.push("some empty var")
}

鉴于坚持使用提供的工具的限制,我们如何才能并行调用,但按顺序处理它们的返回?

【问题讨论】:

  • AJAX1AJAX2 等是什么?他们是承诺吗?
  • 是的,你可以做出承诺
  • 好的。所以你会延长链条N次? 20岁呢?
  • 可惜你没有使用bluebird ;)

标签: javascript asynchronous ecmascript-6 generator q


【解决方案1】:

您可以使用Promise.all().then()

javascript at Answer 返回问题中描述的确切结果

  1. 我们希望为项目的子项发出 N 个并行 ajax 请求。
  2. 返回后,我们希望按顺序处理它们 (1...N)
  3. 我们不想等待所有承诺返回,但我们希望在它们返回时按顺序处理它们。 我们如何并行化调用,但处理它们的返回 顺序?

您可以使用.then() 链接到返回承诺的原始函数或Promise 对象本身在returning 值之前处理承诺,以便按照传递给Promise.all().then() 链接的参数的顺序进行处理给Promise.all()

var n = 0;
var fn = function() {
  return new Promise(function(resolve, reject) {
    console.log("promise " + ++n + " called");
    setTimeout(function(i) {
      resolve(i)
    }, Math.random() * 2500, n)
  })
  // handle requirement 3. here
  .then(function(res) {
    console.log(res);
    return res
  })
}

Promise.all([fn(), fn(), fn()]) // handle requirement 1. here
// handle requirement 2. here
.then(function(data) {
    let [N1, N2, N3] = data;
    console.log(N1, N2, N3);
})

【讨论】:

  • 我也想过。但是 Promise.all 只有在所有 ajax 调用返回后才会继续。我们希望一次触发所有 AJAX 调用,然后在它们返回时按顺序处理它们。
  • 所有 ajax 调用将使用 Promise.all() 立即触发
  • “否决”描述? javascript at Answer 怎么不满足要求“1.我们想为一个项目的孩子发出N个并行ajax请求。2.返回时,我们希望按顺序处理它们(1...N)” , “我们如何并行化调用,但按顺序处理它们的返回?” ?
  • 再一次,原始规范说我们需要在它们返回时进行处理。 Promise.all 在处理之前等待所有返回。就在它说“例如”的地方
  • @guest271314:是的,但是那些then 回调不是连续的。
【解决方案2】:

你可以通过等待循环中的下一个承诺来做到这一点:

const promises = […]; // or created programmatically
for (const promise of promises) {
    const result = yield promise; // await them sequentially
    console.log(result);
}

【讨论】:

  • 真的是yield 用在那里吗?那么应该由谁以及如何迭代生成器并不明显。
  • 为什么这是必要的? Promise.all() 返回问题中描述的预期结果
  • @zerkms: OP 将在 Q.async(function* () {…}) 内部运行它
  • @guest271314 这有点隐藏在问题中,但预期的结果是“[2 和 3 已经到达] 在 1 返回时,它按顺序处理 1,2,3 [无需等待] 4"。 all 解决方案不这样做。
  • @guest271314:是的,我偶尔会将我的答案中的 sn-ps 粘贴到控制台中进行测试,然后不小心按了 Enter,而没有用 替换测试数据 :-)
猜你喜欢
  • 2017-08-27
  • 2021-10-28
  • 2017-10-20
  • 2023-03-17
  • 1970-01-01
  • 2018-05-07
  • 2014-08-03
  • 2016-06-22
相关资源
最近更新 更多