如何在Angular 5中使用$ q.all和$ q.defer?

时间:2018-08-01 23:31:27

标签: angular rxjs observable

我正在尝试将现有的AngularJs代码迁移到Angular5。我目前在forEach函数中运行许多API调用。以前,我曾经为每个功能分别在$ q.defer中运行,在成功或错误函数调用中均运行.resolve()。之后,$ q.all。现在,我不确定如何将它与可观察对象一起使用。

这是我的组件的外观。

testArray = [1,2,3,4,5,.6];
  resultArray = [];

  constructor(private timeoutService: TimeoutService) {
    this.testFn();
  }


 testFn(){
  this.testArray.forEach((n) => {
    this.timeoutService.getItemsCallback(n, this.successFn.bind(this), this.errorFn.bind(this))
  })
 }

 successFn(r){
   this.resultArray.push(r);
   console.log(r)
 }

 errorFn(e){
   this.resultArray.push(e);
   console.log(e);
 }

这是我的服务文件。

public GetItems(request: any): Observable<any> {
    console.log(request)
    return this.http.get(`https://jsonplaceholder.typicode.com/posts/${request}`);
  }


  getItemsCallback(request, successFn, errorFn) {
    this.GetItems(request).
      subscribe(
        response => {
          successFn(response);
        },
        error => { 
          errorFn();
        }
      );
  } 

所有API调用完成后,我想做些事情。我看到有一个名为forkJoin的函数,但是我不确定如何使用它。 这是一个实现这一目的的链接。 https://stackblitz.com/edit/angular-suetah?file=src%2Fapp%2Ftimeout.service.ts

2 个答案:

答案 0 :(得分:0)

如果要执行几个带有存储在数组中的参数的http调用,然后在所有这些调用返回后都必须执行一些特定的操作,则可以考虑采用以下方法。

首先,使用RxJs 6.x的from函数从参数数组中创建一个Observable。

然后,您使用mergeMap(又称flatMap)来将参数数组转换为表示http调用的Observables数组。

最后,您订阅激活Observable链并执行调用,并指定要在Observable链完成时(即当所有http调用都返回时)运行的功能。

代码如下所示

const testArray = [1,2,3,4,5,6];
from(testArray)
.pipe(
  mergeMap(param => this.GetItems(param))
)
.subscribe(
  result => {// do something with the result},
  error => {// do something if an error occurs},
  () => {// this is the function run when all of the httpCalls have returned}
)

答案 1 :(得分:0)

这有使用RxJS的多种解决方案。

此答案是Picci答案的补充。

Picci使用MergeMap。 MergeMap的问题在于,您获得的响应顺序有时可能与请求顺序不同。

ForkJoin,将保留订单并在收到所有响应后返回。

ConcatMap将保留订单,但在完成每个请求后将返回。

如果您不担心在完成所有请求之前等待的时间,我想您可以使用ForkJoin。

会是这样的:

 testArray = [1,2,3,4,5,6];
 obsArray = []
 this.testArray.forEach((n) => {
    this.obsArray.push(this.timeoutService.getItemsCallback(n))
 })

 forkJoin(this.obsArray).subscribe((res) => {
   //Write code for success callback
 },
 (err) => {
   //Write code for error callback
 },
 () => {
   //Write code to do something when all requests are complete
 })

但是,如果您想使用mergeMap或concatMap(请阅读上面的说明并做出决定),则可以执行Picci所做的事情。

如果您决定使用concatMap,只需在他的代码中将mergeMap更改为concatMap。