1

I have a function that creates an array of Observables (batchOfRequests) from an array of items (myItemsArray). Each myItem pushes one Observable (http request) with two parameters from properties of myItem (propertyOne, propertyTwo, etc.) I then use Observable.concat to make the requests for each Observable in the batchOfRequests. This works fine and I can see the data returned from each request in returnedData. However, at this point, I have no idea which myItem in the myItemsArray belongs to each request. Is there a way to link or map each myItem to the Observable that was pushed into the batchOfRequests ?

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;
    }
}
2
  • just for information in concat request go one by one not in parallel form ..you can check on network tab of broswer Commented Mar 17, 2018 at 14:53
  • hi, can you tryout solution given ..let me know it works or not Commented Mar 17, 2018 at 21:09

3 Answers 3

3

forkJoin will emit an array of the responses in the same order as your myItemsArray. Thereby you can match each response back to its request according to its array index:

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];
      ...
    });
  });
}

Note that the use of .catch() ensures that partial failures do not cause the whole batch to fail.

Sign up to request clarification or add additional context in comments.

9 Comments

@PranayRana http requests only ever emit one value
I know but still issue with forkJoin is how it handles fail request ...If any of the executed requests fails it will fail for the whole collection
I am just adding note thats it, your solution works fine i used this in one of my project ...where i want all request to get executed successfully
@PranayRana right you are, but my answer (and the questioners code) uses .catch() to deal with failed requests
Sorry my bad , i can see it now ..but if you add note of failure than it will be helpful
|
0

you can make use of async/wait like as below , and

advantages are

  1. of this its simple (no fancy stuff)
  2. it execute request in parallel
  3. it will return values in order , so 0 promise value is 0, 1 pushed promise in return 1 etc.

check here : 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); }); 
}

Comments

0

You could map the data you want before pushing to the array. Like so:

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);
}

instead of using map after filling the array you could also do your error-catching already in the loop:

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.