在列表上异步操作时保留结果的顺序

时间:2017-03-19 11:47:37

标签: javascript asynchronous rxjs

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

这里是小提琴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"

1 个答案:

答案 0 :(得分:3)

这实际上取决于您需要使用Promises的方式和方式。你现在所拥有的东西根本不需要RxJS,因为你只是创建一个Promises数组,然后在每个上面调用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()能够等待所有Promise完成,而不必担心它。