Nikolas Soares
Nikolas Soares

Reputation: 489

how to call a function after the termination of another function in angular

I have 3 functions and I would like to call one after the other

openTryFunction(){
    // function one
    this.functionOne();
    // after function one
    this.functionTwo();
    // after function two
    this.functionTree(); }

Upvotes: 14

Views: 54499

Answers (6)

hamilton.lima
hamilton.lima

Reputation: 1918

Look at this example where each function returns an Observable and the sequence of execution is controlled by a concat function.

export class AppComponent implements OnInit {
  name = 'Angular';
  values = [];

  first(): Observable<string> {
    return of('first');
  }

  second(): Observable<string> {
    return of('second');
  }

  afterSecond(): Observable<string> {
    return of('secondish');
  }

  third(): Observable<string> {
    return of('third');
  }

  ngOnInit() {
    let sequence = concat([
      this.first, 
      this.second, 
      this.afterSecond, 
      this.third]);

    sequence.subscribe(currentFunction => {
      currentFunction().subscribe(value => {
        this.values.push(value);
      })
    });
  }

}

I like the concat function as it build an Observable of the functions we add to the list.

Note that this call sequence.subscribe(currentFunction each value in currentFunction will be a function, and in order to have the actual value of it, as it is an Observable you need to subscribe to it.

Please see the full example here: https://stackblitz.com/edit/angular-functions-in-sequence?file=src%2Fapp%2Fapp.component.ts

Upvotes: 2

SiddAjmera
SiddAjmera

Reputation: 39482

So you have three functions functionOne, functionTwo, and functionThree. There can be multiple PnCs of whether any of these functions is synchronous or asynchronous.

Let's generalize these scenarios into two main categories:

  1. All are synchronous: If this is the case, your code is going to run one after the other(synchronously).

  2. If any of the function is async: If this is the case, then the function that is async in nature should let the function that is supposed to be called after that, to know that it has terminated. In this case, you can either return a Promise/Observable from that async function. Or you can pass it a callback function that will get called after the async function finishes execution.

Two examples of this would be:

  1. Let's say all these functions are async in nature and all these functions return an Observable:

Then you should be writing it like:

openTryFunction() {
  this.functionOne()
    .subscribe(
      () => this.functionTwo()
              .subscribe(() => this.functionThree()
                                 .subscribe(() => console.log('Function three terminated')))
    );
}
  1. If your functionOne and functionTwo returns a promise, then,:

openTryFunction() {
  this.functionOne().then(() => {
    this.functionTwo().then(() => this.functionThree());
  });
}

Update:

You can also use async and await for a cleaner code. Here's a simple yet concrete example for the same:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  users;

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.getAllData();
  }

  getUsers() {
    return this.http.get('https://jsonplaceholder.typicode.com/users')
      .toPromise();
  }

  getUserPosts(userId) {
    return this.http.get(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`)
      .toPromise();
  }

  getPostComments(postId) {
    return this.http.get(`https://jsonplaceholder.typicode.com/comments?postId=${postId}`)
      .toPromise();
  }

  async getAllData() {
    const users = await this.getUsers();
    const posts = await this.getUserPosts(users[0].id);
    const comments = await this.getPostComments(posts[0].id);

    console.log(users);
    console.log(posts);
    console.log(comments);
  }

}

Here's a StackBlitz for the same.

Hope that makes sense.

Upvotes: 22

John Gallego
John Gallego

Reputation: 691

If your functions are synchronous what you are doing is fine. If they are asynchronous and they return promises then you can string them together as so:

fOne()
  .then(() => {
    fTwo()
 } ).then(() => {
  fThree()
});

Alternatively you can use an async await.

async function tasks() {
  await fOne();
 await fTwo();
 await fThree();
}

Be sure to us try catch to handle exceptions.

If your functions return observables then concatMap is your friend.

fOne()
    .concatMap(() => fTwo())
    .concatMap(() => fThree());

Given your last function Does not return a promise you can omit await on the last call assuming you use async await.

Upvotes: 4

Rohit Sharma
Rohit Sharma

Reputation: 3334

You can use Promise:

functionOne(): Promise<any> {
    return Promise.resolve((() => {
        // code here
        return 'from first'; // return whatever you want not neccessory
    })());
}

functionTwo(): Promise<any> {
    return Promise.resolve((() => {
        // code here
        return 'from second'; // return whatever you want not neccessory
    })());
}

functionThree() {
    // code here
}



this.functionOne().then(data1 => {
    console.log(data1);
    this.functionTwo().then(data2 => {
        console.log(data2);
        this.functionThree();
    });
});

Upvotes: 4

FAISAL
FAISAL

Reputation: 34691

If the functions return an observable, then simply call the next function in subscribe. Otherwise, return a promise from each function. Then you can chain the called functions.

functionOne() {
    return new Promise((resolve) => {
        //
        // Your function implementation
        //
        // Resolve the promise at the end
        resolve(); 
    });
}

functionTwo() {
    return new Promise((resolve) => {
        //
        // Your function implementation
        //
        // Resolve the promise at the end
        resolve(); 
    });
}

functionThree() {
    return new Promise((resolve) => {
        //
        // Your function implementation
        //
        // Resolve the promise at the end
        resolve(); 
    });
}


openTryFunction(){
    // function one
    this.functionOne().then(() => {
        // after function one
        this.functionTwo().then(() => {
            // after function two
            this.functionTree(); 
        });        
    });
}

Upvotes: 1

Mohammad Taherian
Mohammad Taherian

Reputation: 1694

you can try this,

openTryFunction(){
this.functionOne().then(()=>{this.functionTwo().then(() => {this.functionTree()})})}

function 3 will run when 2 is done and 2 will run when 1 is done.

Upvotes: 0

Related Questions