简体   繁体   中英

Angular2 - How to chain async http requests and stop if fails

I have an array of HTTP requests that I need to fire in certain order, but if any of the previous one fails then none of the following ones is going to be executed.

  1. How can I achieve that?

  2. What's the best approach?

I need something like:

  let failed: boolean = false;
  payloadArray.forEach(payload => {
     if (!failed) {
     http.post(this.url, payload, this.options)
     .map((res: Response) => {
        return res.json;
      })
    .catch((error: any) => {
          failed = true;
          Observable.throw(error.json().error || 'Server error')
       });
     }
  }

This would require an Observable creator that merged the emitted values, but only subscribed in sequence after each completed. I don't think there is anything like that in the RxJs library.

I did write a factory method that I think would yield what you want:

public sequence(requests: Array<Observable<Response>>): Observable<Response[]> {
    return Observable.create((observer) => {
        const output = [];

        function executeHttp() {
            const request = requests.pop();
            if (request) {
                request.take(1).subscribe((value) => {
                    output.push(value);
                    executeHttp();
                }, (ex) => {
                    observer.error(ex);
                });
            } else {
                observer.next(output);
                observer.complete();
            }
        }

        executeHttp();
    });
}

Note that I added a take(1) operator to the HTTP observables. This was done to have the HTTP observables destroyed after they yield a response. So that you don't have to call unsubscribe. You can use take(1) or first() which do the same thing, but they work differently when there is nothing emitted.

If you find operators that do what you want. Please let me know.

if you want to send multiple HTTP requests, use ForkJoin . as for you question Http module handles both success and errors in the response

let failed: boolean = false;
let sampleArr = [];

payloadArray.forEach(payload => {
    if (!failed) {
        sampleArr.push(this.http.post(this.url, payload, this.options))
    }
})

Observable.forkJoin(sampleArr).subscribe(
    (data) => this.data = data, 
    (err) => Observable.throw(err.json().error || 'Server error')

); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM