Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 链接两个以上的角度可观察调用_Angular_Rxjs - Fatal编程技术网

Angular 链接两个以上的角度可观察调用

Angular 链接两个以上的角度可观察调用,angular,rxjs,Angular,Rxjs,我目前正在使用Angular 5服务,我需要链接四个独立的可观察呼叫,每个后续呼叫使用部分或所有先前呼叫的数据。我见过一些组合两个调用的示例,但我不知道如何使用两个以上的调用(并且试图通过flatMap扩展它们,导致先前调用的数据在后续调用中不可用) CallOne返回可观察的 然后,我需要做一些过滤来选择一个特定的Foo CallTwo需要Foo并返回observeable 然后,我需要进行一些筛选以选择特定的FooTwo CallThree需要FooTwo并返回observeabl

我目前正在使用Angular 5服务,我需要链接四个独立的可观察呼叫,每个后续呼叫使用部分或所有先前呼叫的数据。我见过一些组合两个调用的示例,但我不知道如何使用两个以上的调用(并且试图通过
flatMap
扩展它们,导致先前调用的数据在后续调用中不可用)

  • CallOne
    返回可观察的
    
    
    • 然后,我需要做一些过滤来选择一个特定的
      Foo
  • CallTwo
    需要
    Foo
    并返回
    observeable
    • 然后,我需要进行一些筛选以选择特定的
      FooTwo
  • CallThree
    需要
    FooTwo
    并返回
    observeable
    • 然后,我需要进行一些筛选以选择特定的
      FooThree
  • CallFour
    需要一个
    Foo
    、一个
    FooTwo
    和一个
    FooThree
    并返回
    可观察的

之后,我需要访问所选的
Foo
FooTwo
FooThree
和特定的

您可以使用
mergeMap
forkJoin
,使用forkJoin,您可以随时触发并行请求,直到所有请求完成

Observable.forkJoin(
    call1(params),
    call2(params),
    call3(params)
).subscribe((responses) => {
    // responses[0] -> response of call1
    // responses[1] -> response of call2
    // responses[2] -> response of call3
})
但是,如果要使其同步并使请求依赖于上一个调用,可以这样做

const request1$ = Rx.Observable.of('response1').delay(2000);
const request2$ = Rx.Observable.of('response2').delay(100);

Rx.Observable.forkJoin(request1$, request2$)
  .subscribe(res => console.log(`forkJoin: ${res}`));

  • CallOne
    返回可观察的
    
    
    • 然后,我需要做一些过滤来选择一个特定的
      Foo
  • CallTwo
    需要
    Foo
    并返回
    observeable
    • 然后,我需要进行一些筛选以选择特定的
      FooTwo
  • CallThree
    需要
    FooTwo
    并返回
    observeable
    • 然后,我需要进行一些筛选以选择特定的
      FooThree
  • CallFour
    需要一个
    Foo
    、一个
    FooTwo
    和一个
    FooThree
    并返回
    可观察的
根据上述规范:

callOne().pipe(
    switchMap((foos: Foo[]) => {
         // filtering foos to get Foo
         this.Foo = <filtered_foo>;
         return callTwo(<filtered_foo>);
    }),
    switchMap((foos2: FooTwo[]) => {
         // filtering foos2 to get FooTwo
         this.FooTwo = <filtered_foo_two>;
         return callThree(<filtered_foo_two>);
    }),
    switchMap((foos3: FooThree[]) => {
         // filtering foos3 to get FooThree
         this.FooThree= <filtered_foo_three>;
         return callFour(this.Foo, this.FooTwo, <filtered_foo_three>);
    })
).subscribe((bars: Bar[]) => {
    this.bars = bars;
    /**
     * this.Foo, this.FooTwo, this.FooThree and this.bars will all be available here
     */
})
callOne().pipe(
开关映射((foos:Foo[])=>{
//过滤Foo以获取Foo
this.Foo=;
返回callTwo();
}),
开关图((foos2:FooTwo[])=>{
//过滤foos2以获取FooTwo
this.FooTwo=;
返回callThree();
}),
开关图((foos3:FooThree[])=>{
//过滤foos3以获得FooThree
这个.FooThree=;
返回callFour(this.Foo,this.FooTwo,);
})
).订阅((条形图:条形图[])=>{
这个。巴=巴;
/**
*这个.Foo、这个.FooTwo、这个.FooThree和这个.bar都可以在这里使用
*/
})

我不确定这是否是解决这一问题的最有效方法,但这对我来说是有效的:

 return this.callOne()
  .flatMap(foo => {
    // foo filter logic here
    return this.callTwo(foo[0].id).map(fooTwo => ({ foo, fooTwo }));
  })
  .flatMap(({ foo, fooTwo }) => {
    // fooTwo filter logic here
    return this.callThree(fooTwo[0].id).map(fooThree => ({ foo, fooTwo, fooThree }));
  })
  .flatMap(({ foo, fooTwo, fooThree }) => {
    return this.callFour(fooTwo[0].id, fooThree[0]).map(bar => ({ foo, fooTwo, fooThree, bar }));
  })
  .do(({ foo, fooTwo, fooThree, bar }) => {
    // additional processing here
    return ({ foo, fooTwo, fooThree, bar });
  });

由于您需要跟踪的值太多,因此我建议您使用
Subject
。这正是
主题
保留值的目的。例如,在您的案例中,您可以使用
行为主题

首先,声明所需的主题:

let call1Subject = new BehaviourSubject<Foo[]>(null);
let call2Subject = new BehaviourSubject<FooTwo[]>(null);
let call3Subject = new BehaviourSubject<FooThree[]>(null);

代码看起来要整洁得多,并且您有一个非常清晰的上下文。
.map()
方法也可以;但是,您的代码很容易变得臃肿,而且很难管理。

我查看了forkJoin,但这不会导致问题,因为我需要同步完成调用(因为后续调用依赖于以前调用的结果)?您仍然可以。我查看了这个特定问题,但是我很难想象如何将其扩展到四个调用,所有调用都需要以前调用的结果。这对您有帮助吗?在我的情况下,它实际上没有帮助,但我将在稍后公布我是如何解决的。链接3
switchMap
应该能够实现您想要的。
return this.callOne()
    .flatMap(foo => {
        // foo filter logic here
        call1Subject.next(foo);
        return this.callTwo(foo[0].id);
    })
    .flatMap(fooTwo => {
        // fooTwo filter logic here
        call2Subject.next(fooTwo);
        return this.callThree(fooTwo[0].id);
    })
    .flatMap(fooThree => {
        call3Subject.next(fooThree);
        let fooTwo = call2Subject.value();
        return this.callFour(fooTwo[0].id, fooThree[0]);
    })
    .map(bar => {
        // additional processing here

        let foo = call1Subject.value();
        let fooTwo = call2Subject.value();
        let fooThree = call3Subject.value();

        return ({foo, fooTwo, fooThree, bar});
    });