并行运行异步任务

时间:2014-10-19 08:25:17

标签: javascript rxjs

在RxJS中,当您想要按顺序运行http请求时 - 将它们链接起来。但我不清楚如何并行运行请求?我在http://reactive-extensions.github.io/learnrx/的示例中看到,他们使用Observable.zip()并行运行2个请求。但是你如何并行运行5个请求呢? 更具体地说,我如何设置以便调用我的函数:

  • 什么时候全部5完成?
  • 第一次完成时?

5 个答案:

答案 0 :(得分:1)

使用combineLatestforkJoin

// Assume you have an array of urls
const urls = [
  "twitter.com/puppies.json", 
  "google.com/puppies.json", 
  "facebook.com/puppies.json"
];

// Let's map these urls to Ajax Observables
const requests = urls.map(url => Rx.DOM.Ajax.getJSON(url))

// Now combine the result from each request into an observable
// Here's combineLatest:
const allThePuppies$ = Rx.Observable.combineLatest(...urls)
// Alternatively, here's forkJoin:
const allThePuppies$ = Rx.Observable.forkJoin(urls)


// When you subscribe to `allThePuppies$`, you'll kick off all your requests in parallel, and your response will contain an array with the results from each request:
allThePuppies$.subscribe(results => {
  const twitterPuppies, googlePuppies, facebookPuppies = results;
  // Do what you must with the respective responses
  // (Presumably in this example you'd show your users some adorable pics of puppies)
})

combineLatest接受任意数量的可观察对象,并且一旦它们每个都发出至少一个值,当任何这些可观察对象触发时,它将从每个可观察对象中发出最新值的数组。

但是,这非常抽象。出于我们的目的,我们知道少数ajax请求实际上只会发出一次。因此,如果我们对少数ajax observable使用combineLatest,我们最终会得到一个observable,它会从每个ajax请求中发出一系列结果。

forkJoincombineLatest类似,但只有在每个成分可观测量完成后才会发出响应数组。

答案 1 :(得分:0)

这是一个相当古老的问题,但没有接受答案。您正在寻找的答案可能非常简单:concatMap

创建promise时,它立即开始执行,因此它们并行执行;当从一个observable发出值时,它们是串行的。

所以结合这两个,对于下面的代码片段,来自promise的observables是并行执行的,并且它们的结果是串行发出的,因为concatMap按照它们的创建顺序将它们放入一个流中。

Rx.Observable.from(urls_array)
.concatMap(function(url) { return Rx.Observable.fromPromise(Promise.resolve($.get(url))) })
.subscribe(
  function(jsonObj) {
    // first result will arrive first
  },
  function(err) { },
  function() {
    // all completed
  }
)

答案 2 :(得分:0)

  

.zip()可以帮助你!

const a$ = Observable.interval(200).take(6) 
const b$ = Observable.interval(300).take(10)
const c$ = Observable.interval(400).take(3)
  .zip(b$,a$)
  .subscribe(v=>console.log(v))


// marble 
-0-1-2-3-4-5|    (a$)
--0--1--2--3--4| (b$)
---0---1---2|    (c$)
  zip(a$, b$)
---[0,0,0]---[1,1,1]---[2,2,2]|

// console.log
[0,0,0]
pause(400ms)
[1,1,1]
pause(400ms)
[2,2,3]
  

.zip(arg1,arg2,(本身,arg1,arg2)=> doSomething())

const a$ = Observable.interval(200).take(6)
const b$ = Observable.interval(300).take(10)
const c$ = Observable.interval(400).take(3)
  .zip(b$,a$, (c,b,a)=>a+b+c)
  .subscribe(v=>console.log(v))

// console.log()
0
pause(400ms)
3 = (1+1+1)
pause(400ms)
9 = (3+3+3)

或者

  

merge()+ flatMap()

import Rx, { Observable } from 'rxjs'
import axios from 'axios'

const promiseA = axios.get('https://jsonplaceholder.typicode.com/users/1')
    , promiseB = axios.get('https://jsonplaceholder.typicode.com/users/2')
    , promiseC = axios.get('https://jsonplaceholder.typicode.com/users/3')

Observable.interval(0).take(1)
  .flatMap(()=>Observable.merge(promiseA, promiseB, promiseC)) 
   // flatMap will resolve the promise for you!
  .map(res=>res.data.username)
  .reduce((arr,item)=>arr.concat(item),[])
  .subscribe(v=>console.log(v)) // [ 'Samantha', 'Antonette', 'Bret' ]

答案 3 :(得分:-1)

也许此链接对您有用[{3}}

答案 4 :(得分:-4)

您可以查看https://www.npmjs.org/package/async

这是一个节点模块,也可以在浏览器中使用。