在angular中对http请求使用可观察对象的最佳方法是什么?

时间:2019-12-13 08:57:04

标签: angular typescript rxjs-observables

我有一个Angular应用,该应用从API获取数据。 首先,我的 detail.component.ts 代码看起来像这样:

//code
getData()
{
this.http.get(url1).subscribe(data1 => 
{/*code: apply certain filter to get a filtered array out*/

this.http.get(url2).subscribe(data2 => 
{/*code: apply certain filter to get a filtered array out*/

this.http.get(url3).subscribe(data3 => 
{/*code: apply certain filter to get a filtered array out*/
})//closing third subscribe form

})//closing second subscribe form
})//closing first subscribe form
}

如您所见,由于所有这些调用相互嵌套,因此将来我将拥有的调用越多,所有信息将变得越混乱。我做了一些研究,发现 observables 可能会解决问题。所以我更改了代码,这就是现在的样子- data.service.ts

//code
getData1()
{this.data1 = this.http.get(this.url1)
return this.data1;}

getData2()
{this.data2 = this.http.get(this.url2)
return this.data2;}

getData3()
{this.data3 = this.http.get(this.url3)
return this.data3;}

detail.component.ts

//code
ngOnInit()
{
this.dataService.getData1().subscribe(data1 => 
{/*code: apply certain filter to get a filtered array out*/

this.dataService.getData2().subscribe(data2 => 
{/*code: apply certain filter to get a filtered array out*/

this.dataService.getData3().subscribe(data3 => 
{/*code: apply certain filter to get a filtered array out*/
})//closing third subscribe form

})//closing second subscribe form
})//closing first subscribe form
}
必须首先执行

Data1 ,因为 Data2 Data3 需要来自 Data1 的已过滤数组的信息。这就是为什么我努力应用诸如 forkJoin 之类的解决方案的原因。所以我的问题是,这是一个好的解决方案,还是您知道一种使代码更少混乱并保持功能的更好方法?

4 个答案:

答案 0 :(得分:4)

Observable可以提供大量的方法和工具来创建美观且可读的管道。这是一个示例:

// my.service.ts
getData1(): Observable {
  return this.httpClient.get();
}

getData2(): Observable {
  return this.httpClient.post();
}

getData3(): Observable {
  return this.httpClient.get();
}
my.component.ts

ngOnInit() {
  this.myService.getData1().pipe(
    map(data => {
      // do what you want with the request answer
      data.id += 1;
      return data;
    }),
    // Pass the modified data and return the Observable for the getData2 request
    switchMap(data => this.myService.getData2(data)),
    // RxJs have a ton of feature to let you play with the data and the pipeline
    // This will wait for 2000ms
    delay(2000),
    // Pass the data returns by getData2 requests to the method getData3
    switchMap(data => this.myService.getData3(data)),
  ).subscribe(
    data => console.log(data); // The result of your pipeline
  )
}

这里发生了什么

  1. getData1()被调用并将返回我们的HttpRequest的Observable
  2. 我们修改之前提出的请求的结果(增加ID)
  3. 我们使用修改后的结果调用getData2,该方法返回请求的Observable
  4. 我们等待2000ms继续
  5. 我们使用getData2请求的结果来调用getData3
  6. 我们订阅此管道以获取最终结果
  

如果您不订阅管道,它将永远不会被触发

RxJs是一个非常庞大且不错的库,可以处理数据,但是太多的人并不真正不善于使用它。

要使用该库,您只需遵循一件事:

  • 切勿将可观察对象放在可观察对象之内

一些问题参考(感谢@LingVu):

答案 1 :(得分:3)

使用switchMap运算符在可观察对象之间切换...

this.dataService.getData1().pipe(
  switchMap(data1 => {
    // do whatever with data1
    return this.dataService.getData2()
  }),
  tap(data2 => {
    // do whatever with data2
    return this.dataService.getData3()
  })
).subscribe()

答案 2 :(得分:1)

您可以尝试使用异步等待方法

async ngOnInit() {
    const data1 = await this.dataService.getData1().toPromise();
    // apply certain filter to get a filtered array out

    const data2 = await this.dataService.getData2().toPromise();
    // apply certain filter to get a filtered array out

    const data3 = await this.dataService.getData3().toPromise();
    // apply certain filter to get a filtered array out
}

您也可以尝试合并地图

this.dataService.getData1()
.pipe(
  map((data1) => {
    // code: filter data here
    return data1;
  }),
  mergeMap((data1) => {
    this.dataService.getData2();
  })
)
.subscribe((finalData) => {
});

或concatMap

this.dataService.getData1()
  .pipe(
    tap(data1 => console.log(data1)),
    concatMap((data1) => {
      this.dataService.getData2(data1);
    }),
    tap(data2 => console.log(data2)),
    concatMap((data2) => {
      this.dataService.getData3(data2);
    }),
    tap(data3 => console.log(data3)),
  )
  .subscribe(result => {
    console.log(result)
  });

答案 3 :(得分:1)

关于链接Rxjs,这是一个常见问题,因此您可以在SO上参考许多以前的问题,其中: