【问题标题】:Preserve order of results when operating asynchronously on a list在列表上异步操作时保留结果的顺序
【发布时间】:2017-03-19 11:47:37
【问题描述】:

我有一个异步函数来处理来自列表的请求,但是当每个请求完成时,它不像之前声明的那样排序(因为它是异步的)。如何异步获取但保留原始顺序?

这是小提琴http://jsbin.com/papunixume/edit?html,js,console

// clear console every single run
console.clear()

// create promise
const cp = (msg, timeout) => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(msg)
    }, timeout)
  })
}

const a = cp('a', 1000)
const b = cp('b', 500)
const c = cp('c', 800)

Rx.Observable.of([a, b, c]).subscribe(val => {
  val.map(res => {
    res.then(x => console.log(x))
  })
})

结果是

"b"
"c"
"a"

预期

"a"
"b"
"c"

【问题讨论】:

  • 如果您希望调用的顺序准确,那么异步处理的意义何在?也许,如果您能告诉我们您想要实现的目标,我们可以帮助您提出一个想法。
  • 你需要分解它,以便异步获取每个资源,然后使用Promise.all 等待所有获取完成;然后按照你想要的顺序处理资源。
  • 你不需要 RxJS:Promise.all([a, b, c])
  • 是的,我认为Promise.all 足以做到这一点。谢谢大家

标签: javascript asynchronous rxjs


【解决方案1】:

这实际上取决于您需要什么以及如何使用 Promise。你现在拥有的根本不需要 RxJS,因为你只是创建了一个 Promise 数组,然后在每个 Promise 上调用 then()

如果您想以更多“RxJS 方式”进行操作,您可以在 Promise 到达时收集结果,同时使用 concatMap() 运算符保持相同的顺序:

Rx.Observable.from([a, b, c])
  .concatMap(promise => promise)
  .subscribe(val => console.log(val));

魔术发生在 concatMap() 内部,因为它识别 Promise 类的实例并以特殊方式处理它们(将它们与 then() 链接并重新发送它们的结果)。

查看演示:http://jsbin.com/gobayoy/4/edit?js,console

或者您可以等到所有 Promise 完成,然后使用 forkJoin() 将它们的所有结果作为单个数组发出:

Rx.Observable.forkJoin(a, b, c)
  .subscribe(val => console.log(val));

查看演示:http://jsbin.com/zojuya/2/edit?js,console

同样,RxJS 会自动处理 Promises,因此forkJoin() 能够等待所有 Promises 完成,而无需担心。

【讨论】:

  • 谢谢@martin。还有Promise.all 我觉得对于不使用 RxJS 的人来说已经足够了?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 2015-05-30
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
相关资源
最近更新 更多