2017-04-10 49 views
3

比方说,我有一个流(观察到的),还有一些元素:如何等待一个承诺,以解决和跳过RxJS中间元素呢?

--a---b-c---d-- 

如果我有一个函数,这些元素之一,并返回一个承诺,就像一个请求,我做的是一个flatMap功能,将得到的反应流将是这样的(大写字母是响应):

--a---b-c---d-- 
----A----B---CD 

但是,这意味着,对于c请求将用于b端请求之前启动。假设我想避免c的请求进行,并有这样的结果:

--a---b-c---d-- 
----A----B----D 

我应该如何解决这个问题?


在下面的代码中,我有一个流在1,2,4和7秒后发射。我有一个request函数,需要两秒钟才能完成。我希望函数只能用1,4和7调用(不能用2,因为1的请求还没有完成)。

const Rx = require('rx'); 

const logNext  = x => console.log(new Date(), 'Next:', x); 
const logError  = x => console.log(new Date(), 'Error:', x); 
const logCompleted =() => console.log(new Date(), 'Completed.'); 

Rx.Observable.fromArray([1, 2, 4, 7]) 
    .flatMap(x => Rx.Observable.of(x).delay(x * 1000)) 
    .flatMapFirst(request) 
    .subscribe(logNext, logError, logCompleted); 


function request(x) { 
    console.log(`Starting request with ${x}`); 
    return new Promise(resolve => { 
    setTimeout(
    () => { 
     console.log(`Finishing request with ${x}`); 
     resolve(x) 
     }, 
     2000 
    ); 
    }) 
} 

flatMapFirst产生正确的响应流,但我想避免通过调用request(2)产生的副作用。

回答

3

你可以尝试,如果你使用rxjs V4使用flatMapFirst。我无法确定运营商是否存在于rxjs v5中。从文档:

的flatMapFirst操作类似于上文描述的flatMap和concatMap 方法,但是,而不是通过从 转化项发射所有由所有观测量使操作者产生的发射的 项源观察的,而不是flatMapFirst传播 第一个可观测专门直到它完成它开始订阅到下一个可观测 之前。当前可观察完成之前来 观测会被丢弃,不会 传播。

代码可能是这样的:

source$.flatMapFirst(makeRequest) 

什么会发生在这里的是,进入b将导致创作的makeRequest(b),与同为c。然而,makeRequest(c)永远不会被订阅,这意味着其影响可能包括其执行不会被执行。

如果makeRequest本身(即的功能,而不是观察到的makeRequest(x)实际上是做一些特效来创建其观察到的输出,并且要防止这种情况,那么你可以使用defer

source$.flatMapFirst(x => Rx.Observable.defer(() => makeRequest(x))) 

您还可以查看以前的答案如下对于更多的例子使用defer

+3

没错,如果你使用的是RxJS 5,'flatMapFirst'已经[重命名](https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md#operators-renamed-or-removed)到['exhaustMap' ](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-exhaustMap)。 – cartant

+0

对不起,虽然这是非常有用的,但我忘了提及我想避免函数被完全调用。那可能吗?我会更新这个问题来包含这个问题。 –

+0

避免函数被完全调用是什么意思?您需要发布一些代码,但原则上,因为您的observable未订阅,所以不会执行任何操作。虽然在某些情况下可以执行请求,但只有响应放在可观察对象中,在这种情况下,您可以在订阅时使用'defer'来推迟请求的执行。如果您发布了一些代码,我可以更清楚地解释这个 – user3743222