IF / ELSE IF / ELSE可观察为条件

时间:2019-02-07 10:45:05

标签: angular typescript rxjs observable rxjs6

我正在尝试创建一种方法来返回可以存储在三个位置之一中的设置。我创建了三个可观察对象,每个可观察对象试图从源中检索设置值。我希望能够以一种创建IF / ELSE IF / ELSE构造的方式“加入”它们,以便只有一个Observable最终发出设置值。从一个可观察的移到另一个可观察的条件是前一个“失败”,即发出的值未通过条件。每个选项的尝试顺序很重要。

到目前为止,我的方法看起来像这样:

getSetting(settingName: string): Observable<any> {

    const optionOne$ = this.getItemAtFirst(settingName).pipe(
        take(1),
        filter(setting => setting && this.isSettingValid(settingName, setting)));

    const optionTwo$ = this.getItemAtSecond().pipe(
        take(1),
        filter(setting => setting && this.isSettingValid(settingName, setting)));

    const optionThree$ = of(this.defaultSettingValue);

    return merge(optionOne$, optionTwo$, optionThree$);
}

这显然不起作用,因为merge不能提供我所需的选择效果。

有什么建议吗?预先感谢!

2 个答案:

答案 0 :(得分:3)

编辑:TL; DR

0.45 0.45 0.45 0.45 0 0 0 0.7 0.7 替换为<embed src="publicMedia/fprefaces/first.pdf#toolbar=0" width="100%" height="100%" oncontextmenu= "return false;" >,然后将merge添加到concat上的管道中:

first

concat顺序地订阅每个可观察对象,这意味着concat(optionOne$, optionTwo$, optionThree$) .pipe( first() ); 首先被订阅,它发出其值,当它完成时,它被取消订阅,然后concat订阅{{1} },依此类推...直到所有可观察对象完成,然后最终将所有值作为数组发出。添加optionOne$可以简化此过程,因为它会在发出第一个值之后完成concat。

您真的需要检查concat内的所有可观察对象是否将完成,否则您可能会遇到其中一个永远不会发出或完成的情况,这将意味着您永远都不会获得值来自optionTwo$

-

假设您的first如果未通过验证,则返回false,然后将concatconcat添加到isSettingValid()中。请参见下面的稍微修改的版本,以及此处的stackblitz

article也是有用的。并且我建议使用这个article的gif动画,以解释操作员及其工作方式-当我试图找出类似的东西时,我总是回到它上面。

我认为这回答了您的问题,因为它发出第一个通过验证的值,而忽略其余值。

pipe()

我还建议像我的代码片段一样删除first(),并将null检查放入验证函数中-如果这样做imo,它只会使过滤器更易于阅读。为了使内容更简洁,您可以考虑将concat()import { of, Observable, concat } from 'rxjs'; import { take, filter, first } from 'rxjs/operators'; function isSettingValid(setting): boolean { return setting !== 'error' ? true : false; } function getSetting(): Observable<any> { const optionOne$ = of('error') .pipe( take(1), filter(setting => isSettingValid(setting)) ); const optionTwo$ = of('second') .pipe( take(1), filter(setting => isSettingValid(setting)) ); const optionThree$ = of('default').pipe( take(1), filter(setting => isSettingValid(setting)) ); return concat(optionOne$, optionTwo$, optionThree$) .pipe( first() // emits only the first value which passes validation then completes ); } getSetting() .subscribe((setting) => { console.log(setting); }) 替换为setting &&和一个具有相同结果的谓词函数:

take(1)

答案 1 :(得分:-2)

应该像链接一样实现。即使使用上述代码,即使您从IndexDB中获取数据,您仍将最终调用MangoDB(等待数据)。除了使之复杂之外,我要做的是将呼叫链接起来。但其全部取决于用例。在这种情况下,我想使用 flatMap 运算符将呼叫链接起来会更好。