3

I'm working on a Angular 4 project and I'm new with Observable.

My goal is to execute one function after the result of three HTTP requests and enrich my models with HTTP request results.

I resolved my problem with observable like following code but I think this is not the correct way:

function loadData(callback: Function): void {
    this.httpRequestUno().subscribe(next => {
        this.httpRequestDue().subscribe(next => {
          this.httpRequestTre().subscribe(next => {
            callback();
          }, error => {
            console.log(error);
          });
        }, error => {
          console.error(error);
        });
      }, error => {
        console.error(error);
      });
}

function httpRequestUno():Observable<any>{
    let self = this;
    return new Observable<any>((observer) => {
        // my http request and...
        self.attributo1 = httpResult;
        observer.next(1);
    });
}

function httpRequestDue():Observable<any>{
    let self = this;    
    return new Observable<any>((observer) => {
        // my http request and...
        self.attributo2 = httpResult;
        observer.next(2);
    });
}

function httpRequestTre():Observable<any>{
    let self = this;    
    return new Observable<any>((observer) => {
        // my http request and...
        self.attributo3 = httpResult;
        observer.next(3);
    });
}

Does RxJS allow to combine multiple actions like following pseudo-code?

function loadData(callback: Function): void {

    this.httpRequestUno().combine(this.httpRequestDue).combine(this.httpRequestTre).subscribe(result => {
        callback();
    });

}

Is there a way to pass all results in one parameters like following pseudo-code?

this.httpRequestUno().combine(this.httpRequestDue).combine(this.httpRequestTre).subscribe(result => {
    let httpRequestUnoResult = result[0];
    let httpRequestDueResult = result[1];
    let httpRequestTreResult = result[2];
    callback();
});

[EDIT]

I've tried Oscar's solution. The problem is that subscribe callback are not executed but if I add one observer.completed() in one function the "completed callback" is executed but I cannot access to data.

I reproduced my case there https://jsfiddle.net/2n6b0ug3/

Thank you a lot

ilMattion
  • 1,841
  • 2
  • 24
  • 47
  • I think what you're looking for is rxjs [`flatMap`](http://reactivex.io/documentation/operators/flatmap.html), check [this](https://stackoverflow.com/a/48012318/2526437) answer. – cyberpirate92 May 03 '18 at 15:33

1 Answers1

5

Yes, with forkJoin operator:

const subscription = forkJoin(
    this.httpRequestUno(),
    this.httpRequestDue(),
    this.httpRequestTre()
).subscribe(value => {
     // value is an array with the results:
     [result-of-request-uno, results-of-rquest-due, result-of-request-tre]
}, error => {

);

In fact, forkJoin can also receive an array of observables, if you want to make the number of requests dynamic, and the resulting observable will complete when all the other observables complete. Of course, if one of the observables throws an error, you'll get an error (the first one). In this case, the result of the other observables will be ignored.

More info: https://www.learnrxjs.io/operators/combination/forkjoin.html

It is, roughly, the equivalent of Promise.all

EDIT

I forked your jsfiddle to fix your example: https://jsfiddle.net/hmv20xjh/1/. The problem in your code is that your observables never complete, and forkJoin returns the last value of an observable, and only does so when they complete. So, in your code, the observable that forkJoin returns just keeps waiting forever and never yields a value.

In mine, though, the observables do complete. forkJoin is a good operator to wait for observables that represent an HTTP request, as they only yield one result and then complete. If you need to merge observables that yield multiple results, without waiting for them to complete, you need to use more complicated operators like flatMap or mergeMap

Oscar Paz
  • 18,084
  • 3
  • 27
  • 42