Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to wait for a function to complete its execution in angular 6 before executing the following code execution?

I have a two functions as below:

refreshAccessToken() {
  let rt = this.injector.get(LocalStorageService);
  var tokenData = rt.getAuthorizationData();
  var refreshToken = tokenData.refresh_token;
  var refreshToken = localStorage.getItem('userRefreshToken');
  if (refreshToken !== null) {
    var data = "grant_type=refresh_token&refresh_token=" + refreshToken;
    var basicAuth = btoa("crmClient1:crmSuperSecret");
    var headerData = {
      "Content-Type": "application/x-www-form-urlencoded",
      "Authorization": "Basic " + basicAuth,
      "No-Auth": "True",
      'Access-Control-Allow-Origin': '*'
    };
    var reqHeader = new HttpHeaders(headerData);
    this.http.post(this.tokenUrl, data, {
        headers: reqHeader
      })
      .subscribe((response: any) => {
        this.localStorageService.setAuthorizationData(response);
        console.log("I need to be called first");
      });
  } else {
    return null;
  }
}

getNewAccessToken(): Observable < string > {
  this.refreshAccessToken();
  console.log("I need to be called as a second value");
  var varTokenData = this.localStorageService.getAuthorizationData();
  var newAccessToken = varTokenData.access_token;
  this.newat = newAccessToken;
  return of(this.newat);
}

I am calling refreshAccessToken() function inside getNewAccessToken() function. Here, the code is doing fine except that the codes:

console.log("I need to be called as a second value");
var varTokenData = this.localStorageService.getAuthorizationData();
var newAccessToken = varTokenData.access_token;
this.newat = newAccessToken;
return of(this.newat);

are executed before the complete execution of function refreshAccessToken(). How do I make other codes wait for execution until the refreshAccessToken() function is completely executed in angular 6?

The error I am getting is as below:

enter image description here

The section of AuthInterceptor from where I a calling getNewAccessToken() function is as below:

//generating new token from refresh_token

handle401Error(req: HttpRequest<any>, next: HttpHandler) {
    console.log("Error 401 called");
    if (!this.isRefreshingToken) {
        this.isRefreshingToken = true;

        // Reset here so that the following requests wait until the token
        // comes back from the refreshToken call.
        this.tokenSubject.next(null);
        return this.loginService.getNewAccessToken()
        .pipe(
            switchMap((newToken: string) => {
                if (newToken) {
                    this.tokenSubject.next(newToken);
                    //this.isRefreshingToken=false;
                    return next.handle(this.addToken(req, newToken));
                }

                // If we don't get a new token, we are in trouble so logout.
                //this.isRefreshingToken=false;
                return this.logout();
            }),
            catchError(error => {
                // If there is an exception calling 'refreshToken', bad news so logout.
                //this.isRefreshingToken=false;
                //console.log(error);
                return this.logout();
            })
        //)

        ),
        finalize(()=>{
            this.isRefreshingToken=false;
        });   
    } else {
        return this.tokenSubject
            .pipe(
                filter(token => token !=null)
            ),
            take(1),
            switchMap((token: string )=> {
                return next.handle(this.addToken(req,token));
            });
    }
}
like image 548
S.Thapa Avatar asked Sep 21 '18 03:09

S.Thapa


People also ask

How do you wait for a function to execute in typescript?

The Typescript wait is one of the features for to wait for the process which is executed by the end-users; it can be applicable for both compile-time and run-time execution the asynchronous process is wrapped over the promises also the user will set the time interval for all the formats like seconds, milliseconds and ...

How do you wait for a function to finish?

Wait for function to finish using async/await keywords As you already know from the Promise explanation above, you need to chain the call to the function that returns a Promise using then/catch functions. The await keyword allows you to wait until the Promise object is resolved or rejected: await first(); second();

How wait for function with subscribe to finish in angular 8?

The second function checkDuplicate() we have subscribed to that function getData() . and we have third function called proceed() in which we call the checkDuplicate() function and once the checkDuplicate() function is completed, we are calling alert("finished").

What is await and async in Angular?

Basically, Async/Await works on top of Promise and allows you to write async code in a synchronous manner. It simplifies the code and makes the flow and logic more understandable. Note that because it no longer uses then and catch chaining anymore, you can handle errors by running try/catch.


2 Answers

You can return an Observable from your refreshAccessToken method:

import { of } from 'rxjs';
import { tap } from 'rxjs/operators';

refreshAccessToken(): Observable<any> {
  ...
  if (refreshToken !== null) {
    ...
    return this.http.post(this.tokenUrl, data, {
      headers: reqHeader
    })
    .pipe(tap(response => this.localStorageService.setAuthorizationData(response)));
  } else {
    return of(null);
  }
}

And then subscribe to it from your getNewAccessToken method like this:

getNewAccessToken(): Observable<string> {
  this.refreshAccessToken()
    .subscribe(response => {
      ...
    });
}

Alternatively:

You could use async/await which were introduced in ES2017. Since they work only with functions dealing with promises and not Observables, you will have to change your functions a bit to return a promise instead of Observable.

Here's how:

import { of } from 'rxjs';
import { tap } from 'rxjs/operators';

refreshAccessToken() {
  ...
  if (refreshToken !== null) {
    ...
    return this.http.post(this.tokenUrl, data, {
      headers: reqHeader
    })
    .pipe(tap(response => this.localStorageService.setAuthorizationData(response)))
    .toPromise();
  } else {
    return of(null).toPromise();
  }
}

And then declare getNewAccessTokenas async and await refreshAccessToken:

async getNewAccessToken() {
  await this.refreshAccessToken();
  ...
}
like image 60
SiddAjmera Avatar answered Nov 15 '22 05:11

SiddAjmera


import { forkJoin } from "rxjs";

async ngOnInit() {
  await this.getDataFromMultipleApis().then(data=>{
    console.log(data);
  });
}
getDataFromMultipleApis(){
   return new Promise((res, rej) => {
      forkJoin(
        this.Service.api1(),
        this.Service.api2()
      ).subscribe(docs => {        
        res(docs);
      });
    });
}
like image 44
Harsha Vardhan Reddy N Avatar answered Nov 15 '22 06:11

Harsha Vardhan Reddy N