Wait for Asynchronous Functions to Finish in Angular

Wait for Asynchronous Functions to Finish in Angular

So I was working on a new component in Angular and in the ngOninit I have the following asynchronous functions below...

This.getUserProfile needs to be finished before I can call this.getPrivateGroup() and this.getPrivateGroup() needs to be finished before I can call this.loadGroupPosts(). I know I could write these functions inside the callback of the asynchronous requests, but I was wondering if there is a way to keep it in ngOnInit to keep it cleaner?

Anyone has an idea?

ngOnInit() {

    this.getUserProfile();

    // my-workplace depends on a private group and we need to fetch that group and edit
    // the group data before we proceed and get the group post
    if (this.isItMyWorkplace) {
      this.getPrivateGroup();
    }
    this.loadGroupPosts();
  }

getUserProfile() {
    this._userService.getUser()
      .subscribe((res) => {
        this.user = res.user;
        console.log('log user', this.user);
        this.profileImage = res.user['profile_pic'];
        this.profileImage = this.BASE_URL + `/uploads/${this.profileImage}`;
      }, (err) => {
        this.alert.class = 'alert alert-danger';
        if (err.status === 401) {
          this.alert.message = err.error.message;
          setTimeout(() => {
            localStorage.clear();
            this._router.navigate(['']);
          }, 3000);
        } else if (err.status) {
          this.alert.class = err.error.message;
        } else {
          this.alert.message = 'Error! either server is down or no internet connection';
        }
      });
  }



getPrivateGroup() {
    console.log('user check', this.user);
    this.groupService.getPrivateGroup(`${this.user.first_name}${this.user.last_name}`)
      .subscribe((group) => {
          console.log('received response', group)
    })
  }

 // !--LOAD ALL THE GROUP POSTS ON INIT--! //
  loadGroupPosts() {
    this.isLoading$.next(true);

    this.postService.getGroupPosts(this.group_id)
      .subscribe((res) => {
        // console.log('Group posts:', res);
        this.posts = res['posts'];
        console.log('Group posts:', this.posts);
        this.isLoading$.next(false);
        this.show_new_posts_badge = 0;
      }, (err) => {
        swal("Error!", "Error while retrieving the posts " + err, "danger");
      });
  }
  // !--LOAD ALL THE GROUP POSTS ON INIT--! //
7

4 Answers

You can use basic promises with async/await.

async ngOnInit() {

    await this.getUserProfile(); // <-- 1. change

    // my-workplace depends on a private group and we need to fetch that group and edit
    // the group data before we proceed and get the group post
    if (this.isItMyWorkplace) {
      this.getPrivateGroup();
    }
    this.loadGroupPosts();
  }

async getUserProfile() {
    this._userService.getUser()
      .subscribe((res) => {
        this.user = res.user;
        console.log('log user', this.user);
        this.profileImage = res.user['profile_pic'];
        this.profileImage = this.BASE_URL + `/uploads/${this.profileImage}`;
        return true; // <-- this
      }, (err) => {
        this.alert.class = 'alert alert-danger';
        if (err.status === 401) {
          this.alert.message = err.error.message;
          setTimeout(() => {
            localStorage.clear();
            this._router.navigate(['']);
          }, 3000);
        } else if (err.status) {
          this.alert.class = err.error.message;
        } else {
          this.alert.message = 'Error! either server is down or no internet connection';
        }
        throw err;
      });

}

4

You could instead leverage RxJS and use a switchMap something like this (syntax NOT checked):

getData(): Observable<string[]> {
  return this._userService.getUser()
    .pipe(
      switchMap(userInfo=> {
         return this.getPrivateGroup();
      }),
      catchError(this.someErrorHandler)
    );
}

One way to do is, return the Observable instead of subscribing in the getPrivateGroup()

getPrivateGroup() {
    console.log('user check', this.user);
    return this.groupService.getPrivateGroup(`${this.user.first_name}${this.user.last_name}`)

  }

And then, subscribe to the data where you want the chain the this.loadGroupPosts()

     if (this.isItMyWorkplace) {
          this.getPrivateGroup().subscribe(group => {
          this.group = group; //you probably want to assign the group data
          this.loadGroupPosts()});
        }

you could also use the 3rd part of your subscribe function when its completed i am not quite sure if this is a clean solution, in my opinion it is.

ngOnInit() {
this.getUserProfile();
}


getUserProfile() {
this._userService.getUser()
    .subscribe((res) => {
        this.user = res.user;
        console.log('log user', this.user);
        this.profileImage = res.user['profile_pic'];
        this.profileImage = this.BASE_URL + `/uploads/${this.profileImage}`;
    }, (err) => {
        this.alert.class = 'alert alert-danger';
        if (err.status === 401) {
            this.alert.message = err.error.message;
            setTimeout(() => {
                localStorage.clear();
                this._router.navigate(['']);
            }, 3000);
        } else if (err.status) {
            this.alert.class = err.error.message;
        } else {
            this.alert.message = 'Error! either server is down or no internet connection';
        }
    }, () => {
        // my-workplace depends on a private group and we need to fetch that group and edit
        // the group data before we proceed and get the group post
        if (this.isItMyWorkplace) {
            this.getPrivateGroup();
        }
    });
}

getPrivateGroup() {
console.log('user check', this.user);
this.groupService.getPrivateGroup(`${this.user.first_name}${this.user.last_name}`)
    .subscribe((group) => {
        console.log('received response', group)
    }, error => {
        console.log(error)
    }, () => {
        this.loadGroupPosts();
    })
}

loadGroupPosts() {
this.isLoading$.next(true);

this.postService.getGroupPosts(this.group_id)
    .subscribe((res) => {
        // console.log('Group posts:', res);
        this.posts = res['posts'];
        console.log('Group posts:', this.posts);
        this.isLoading$.next(false);
        this.show_new_posts_badge = 0;
    }, (err) => {
        swal("Error!", "Error while retrieving the posts " + err, "danger");
    });
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

David Miller
Author

David Miller

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.