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

MH *_*har 4 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))
  })
})
Run Code Online (Sandbox Code Playgroud)

结果是

"b"
"c"
"a"
Run Code Online (Sandbox Code Playgroud)

预期的

"a"
"b"
"c"
Run Code Online (Sandbox Code Playgroud)

mar*_*tin 5

这实际上取决于您需要使用 Promise 的内容和方式。您现在拥有的根本不需要 RxJS,因为您只是创建了一个 Promise 数组,然后调用then()它们中的每一个。

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

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

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

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

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

Rx.Observable.forkJoin(a, b, c)
  .subscribe(val => console.log(val));
Run Code Online (Sandbox Code Playgroud)

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

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