如何映射或访问Observables数组(http请求)的输入

时间:2018-03-17 01:32:11

标签: angular typescript rxjs

我有一个函数,它从一个项目数组(myItemsArray)创建一个Observables数组(batchOfRequests)。每个myItem使用myItem属性(propertyOne,propertyTwo等)中的两个参数推送一个Observable(http请求)然后使用Observable.concat在batchOfRequests中为每个Observable发出请求。这工作正常,我可以在returnedData中看到每个请求返回的数据。但是,此时,我不知道myItemsArray中的哪个myItem属于每个请求。有没有办法将每个myItem链接或映射到推入batchOfRequests的Observable?

performMultipleRequests(): void
{
let batchOfRequests: Observable<any>[] = [];

for (let myItem of this.myItemsArray)
{            

this.batchOfTrendRequests.push(this.myService.makeHTTPCall(myItem.propertyOne, myItem.propertyTwo))

}

this.batchOfRequests = this.batchOfRequests.map(obs =>
{
    return obs.catch(err => Observable.of(err));
});       

Observable.concat(...this.batchOfRequests)
    .finally(() =>
    {
        return;
    })
    .subscribe((returnedData: any) =>
    {
        // do something with my returned data... but I need myItem information as well
        return;
    }), (error) =>
    {
            return;
    }
}

3 个答案:

答案 0 :(得分:3)

forkJoin将以与myItemsArray相同的顺序发出一系列响应。因此,您可以根据其数组索引将每个响应匹配回其请求:

performMultipleRequests(): void {
  let batchOfRequests: this.myItemsArray.map(myItem => 
    this.myService.makeHTTPCall(myItem.propertyOne, myItem.propertyTwo)
      .catch(err => Observable.of(err))
  );

  Observable.forkJoin(...batchOfRequests).subscribe((myResponsesArray: any[]) => {
    myResponsesArray.forEach((returnedData, index) => {
      // lookup myItem corresponding to this returnedData
      const myItem = this.myItemsArray[index];
      ...
    });
  });
}

请注意,使用.catch()可确保部分失败不会导致整批失败。

答案 1 :(得分:0)

您可以在推送到阵列之前映射所需的数据。像这样:

let batchOfRequests: Observable<{ myData: any, httpResponse: any }>[] = [];
for (let myItem of this.myItemsArray)
{
    const httpRequest = this.myService.makeHTTPCall(myItem.propertyOne, myItem.propertyTwo);
    const mappedRequest = httpRequest.map(res => { 
        return { myData: myItem, httpResponse: res };
    });

    batchOfRequests.push(mappedRequest);
}

而不是在填充数组后使用map,你也可以在循环中进行错误捕获:

let mappedRequest = httpRequest.map(res => { 
    return { myData: myItem, httpResponse: res };
});

mappedRequest = mappedRequest.catch(err => Observable.of(err));

答案 2 :(得分:0)

您可以使用async / wait,如下所示,

优点是

  1. 这简单(没有花哨的东西)
  2. 并行执行请求
  3. 它将按顺序返回值,因此0保证值为0,1推送承诺返回1等。
  4. 点击此处:JavaScript Demo: Promise.all()

    async/wait in trypscript

    async performMultipleRequests(): void
    {
      let batchOfRequests: Promise<any>[] = [];
    
      for (let myItem of this.myItemsArray)
      {            
        this.batchOfTrendRequests.push
          (this.myService.makeHTTPCall
             (myItem.propertyOne, myItem.propertyTwo).toPromise());
    
      }
      //this will return you array of all completed request
      const allRetunValue = await Promise.all(batchOfTrendRequests);
    
      allRetunValue.forEach(retval=> { console.log(retval); }); 
    }