Home > Mobile >  Angular 12/rxjs: Wait for listfetching (i.e. via forkjoin/combineLatest/etc) to finish before procee
Angular 12/rxjs: Wait for listfetching (i.e. via forkjoin/combineLatest/etc) to finish before procee

Time:09-22

In my ngOnInit, I would like to wait for all requests of fetchLists to finish before proceeding.

We therefore have two steps:

  • step 1: fetch all lists in any order/in parallel
  • step 2: once step 1 finished, proceed with own logic which includes another subscription...
  ngOnInit(): void {
    //step 1: fetch all lists in any random order
    this.fetchLists();

    //step 2: once finished, proceed with logic
    this.route.params.subscribe(params =>
      if (params[`id`]) {
        this.isNew = false;
        this.httpHandler.getUser(params[`id`])
          .subscribe(user => this.user = user
      } else {
        this.isNew = true;
      });
  }

  fetchLists(): void {
    this.httpHandlerCached.getListsA()
      .subscribe(listA => this.listA = listA);
    this.httpHandlerCached.getListsB()
      .subscribe(listB => this.listB = listB);
    this.httpHandlerCached.getListsC()
      .subscribe(listC => this.listC = listC);
  }

Above code has the trouble, that step 2 will not wait for step 1 to finish.

My only solution includes using forkjoin or combinelatest while combining step 1 and step 2. And that's something that I really need to avoid. Step 1 and step 2 must be in separate methods.

Proposed ideas using forkjoin or combinelatest are therefore not satisfying solutions:

//Solution 1: forkJoin "merging" step 1 and step 2 in one big codeblock
ngOnInit(): void {
  forkJoin([
      this.httpHandlerCached.getListsA(),
      this.httpHandlerCached.getListsB(),
      this.httpHandlerCached.getListsC(),
      this.route.params.pipe(take(1))
    ]).subscribe(res => {
        this.listA = res[0];
        this.listB = res[1];
        this.listC = res[2];
        if (res[3][`id`]) {
          this.isNew = false;
          this.httpHandler.getUser(res[3][`id`])
            .subscribe(user => this.user = user);
        } else {
          this.isNew = true;
        }
    });
}

//Solution 2: combineLatest "merging" step 1 and step 2 in one big codeblock
ngOnInit(): void {
  combineLatest([
          this.httpHandlerCached.getListsA(),
          this.httpHandlerCached.getListsB(),
          this.httpHandlerCached.getListsC(),
          this.route.params
        ]).subscribe(res => {
            this.listA = res[0];
            this.listB = res[1];
            this.listC = res[2];
            if (res[3][`id`]) {
              this.isNew = false;
              this.httpHandler.getUser(res[3][`id`])
                .subscribe(user => this.user = user);
            } else {
              this.isNew = true;
            }
        });
}

Again, in above solutions step1 and step2 are both just put together. However, I need to keep the fetching of the lists in a separate method such as "fetchList()" as above, which I simply want to wait for to be finished before proceeding with step 2.

CodePudding user response:

You could use forkJoin like this

forkJoin([
      this.httpHandlerCached.getListsA().pipe(first()),
      this.httpHandlerCached.getListsB().pipe(first()),
      this.httpHandlerCached.getListsC().pipe(first())
]).subscribe(([listA, listB, listC]) => {
    this.listA = listA;
    this.listB = listB;
    this.listC = listC;

    /// Now setup router subscriptions
    this.initRouter();
})

 
initRouter(){

    /// Do sth
}
  • Related