RxJS 6有条件地管道可观察

时间:2018-08-15 13:52:44

标签: angular rxjs

我有一个现有函数,该函数完成调用HTTP终结点的大量工作,该工作负责管理Angular组件中的某些逻辑。出现了一个需求,以便在某些情况下,我们需要调用所有现有逻辑,但是还需要进行另一个HTTP调用。下面是我的尝试的带注释的版本。

public resolveComponent(action: string) {
        //if called with no parameters, don't do anything
        //otherwise, call one of the two endpoints.     
        let preAction = (x: any) => {
            if (action === "replay") {
                return this.remediationService
                           .replayRemediation(this.workflow.Id);
            }
            else if (action === "remove") {
                return this.remediationService
                           .removeRemediation(this.workflow.Id);
            }
            else {
                return of([]);
            }
        }

        this.remediationService
            .resolveComponent(component)
            .pipe(
                //the line below was what I added after new requirement
                mergeMap(preAction),
                mergeMap(x => {
                    //grabs updated data from server
                    return this.remediationService.remediationComponent(component.Id);
                })
            )
            .subscribe((x: SomeModel) => {
                    //logic happens
                });
}

这可以按预期执行工作,但这是有条件链接可观察对象的最好方法吗?

5 个答案:

答案 0 :(得分:4)

您可以添加自己的pipeIf

import { from, Observable, of, NEVER } from 'rxjs';
import { mergeMap, map, filter } from 'rxjs/operators';

from([10, 11, 12, 13])
  .pipe(
    map(x => x + 10),
    pipeIf(x => x > 21,
      filter(x => x > 22),
      map(x => x + 100)
    ),
)
  .subscribe(console.log);

function pipeIf(predicate, ...pipes) {
  return function (source) {
    return source.pipe(
      mergeMap(value => predicate(value) ? of(value).pipe(...pipes) : of(value))
    )
  }
}

// 20
// 21
// 123

答案 1 :(得分:4)

使用iif rxjs。

iif接受一个条件函数和两个Observable。什么时候  *订阅了操作员返回的Observable,将调用条件函数。

https://www.learnrxjs.io/operators/conditional/iif.html

答案 2 :(得分:2)

iif 可以有条件地写入 observable:

  • iif(() => cond, obs1, obs2) = cond ? obs1 : obs2
  • iif(() => cond, obs1) = cond ? obs1 : EMPTY

但是 iif 不适用于运营商。如果要在 .pipe() 中有条件地编写运算符,请使用:

cond ? delay(1000) : interval(500)

对于空运算符,使用 identity:

import { identity } from 'rxjs'
cond ? delay(1000) : identity

其中 identity 实际上是 x => x

答案 3 :(得分:0)

这个对我有用,

in html template
  <formio [form]="formDescription" (submit)="submit.emit($event)" "" [submission]="submission"></formio>
in typescript 
export class FormioViewComponent implements OnInit {

  @Input() formDescription;
  @Input() submission:any;

  @Output() submit :EventEmitter<any> = new EventEmitter();
  constructor() { }

  ngOnInit() {
  }

}

答案 4 :(得分:0)

您可能只使用merge()(如果需要流是连续的,则使用concat()而不是两个mergeMap(),因为您似乎不需要新的输出流作为现有流的输入:

const replayObservable = of("Has been Replayed");
const removeObservable = of("Has been Removed");
const existingObservable = of(
  "Finally, do what you already did before the CR."
);
const resolveComponent = (action?: string) => {
  const newSource = of();
  const targetWithoutNull = newSource.pipe(
    merge(
      iif(
        () => !!action,
        iif(() => action == "replay", replayObservable, removeObservable)
      ),
      existingObservable
    )
  );
  targetWithoutNull.subscribe(x => console.log(x));
};

resolveComponent("replay");
resolveComponent("remove");
resolveComponent();

请注意,第一个iif()仅具有2个参数。如果条件指向一个未定义的参数,iif()将完成流,因此在这种情况下,将仅预订existingObservable。

查看此运行:https://stackblitz.com/edit/rxjs-7ztk16