How to wait for a function to finish its execution in angular 2.?
Asked Answered
H

2

6

Below is my code, I want login() and authenticated() functions to wait for getProfile() function to finish its execution. I tried several ways like promise etc. but I couldn't implement it. Please suggest me the solution.

import { Injectable }      from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import { myConfig }        from './auth.config';

// Avoid name not found warnings
declare var Auth0Lock: any;

@Injectable()
export class Auth {
  // Configure Auth0
  lock = new Auth0Lock(myConfig.clientID, myConfig.domain, {
    additionalSignUpFields: [{
      name: "address",                              // required
      placeholder: "enter your address",            // required
      icon: "https://example.com/address_icon.png", // optional
      validator: function(value) {                  // optional
        // only accept addresses with more than 10 chars
        return value.length > 10;
      }
    }]
  });

  //Store profile object in auth class
  userProfile: any;

  constructor() {
    this.getProfile();  //I want here this function to finish its work
  }


  getProfile() {
    // Set userProfile attribute if already saved profile
    this.userProfile = JSON.parse(localStorage.getItem('profile'));

    // Add callback for lock `authenticated` event
    this.lock.on("authenticated", (authResult) => {
      localStorage.setItem('id_token', authResult.idToken);

      // Fetch profile information
      this.lock.getProfile(authResult.idToken, (error, profile) => {
        if (error) {
          // Handle error
          alert(error);
          return;
        }

        profile.user_metadata = profile.user_metadata || {};
        localStorage.setItem('profile', JSON.stringify(profile));
        this.userProfile = profile;
      });
    });
  };

  public login() {
    this.lock.show();
    this.getProfile();  //I want here this function to finish its work
  };

  public authenticated() {
    this.getProfile();  //I want here this function to finish its work
    return tokenNotExpired();
  };

  public logout() {
    // Remove token and profile from localStorage
    localStorage.removeItem('id_token');
    localStorage.removeItem('profile');
    this.userProfile = undefined;
  };
}
Heartbreaking answered 22/9, 2016 at 17:38 Comment(1)
your getProfile function should return a promise/observable and then login and authenticated will be able to connect to the promise/observable and performs actions once it is doneStipulate
G
6

Like you saw in the comments, you have to use Promise or Observable to achieve this, since your behaviour is pretty simple, you should use Promise because Observable will have a lot of features you don't need in this case.

Here is the Promise version of your service:

import { Injectable }      from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import { myConfig }        from './auth.config';

// Avoid name not found warnings
declare var Auth0Lock: any;

@Injectable()
export class Auth {
  // Configure Auth0
  lock = new Auth0Lock(myConfig.clientID, myConfig.domain, {
    additionalSignUpFields: [{
      name: "address",                              // required
      placeholder: "enter your address",            // required
      icon: "https://example.com/address_icon.png", // optional
      validator: function(value) {                  // optional
        // only accept addresses with more than 10 chars
        return value.length > 10;
      }
    }]
  });

//Store profile object in auth class
userProfile: any;

constructor() {
    this.getProfile();  //I want here this function to finish its work
  }


getProfile():Promise<void> {
    return new Promise<void>(resolve => {
    // Set userProfile attribute if already saved profile
    this.userProfile = JSON.parse(localStorage.getItem('profile'));

    // Add callback for lock `authenticated` event
    this.lock.on("authenticated", (authResult) => {
      localStorage.setItem('id_token', authResult.idToken);

      // Fetch profile information
      this.lock.getProfile(authResult.idToken, (error, profile) => {
        if (error) {
          // Handle error
          alert(error);
          return;
        }

        profile.user_metadata = profile.user_metadata || {};
        localStorage.setItem('profile', JSON.stringify(profile));
        this.userProfile = profile;
        resolve()
      });
    });
   })
};

public login(): Promise<void>{
    this.lock.show();
    return this.getProfile();  //I want here this function to finish its work
  };

  public authenticated():void{
    this.getProfile().then( () => {  
        return tokenNotExpired();
    });
  };

  public logout():void {
    // Remove token and profile from localStorage
    localStorage.removeItem('id_token');
    localStorage.removeItem('profile');
    this.userProfile = undefined;
  };
}

More on Promise here

Goffer answered 22/9, 2016 at 19:22 Comment(2)
I'm getting following warning and its still not working:- lock.min.js:2 (node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.Heartbreaking
This is not an error but a warning, you have a possible memory leak because you added too much listeners, you should check your code quality (you often find this kind of error because of listeners created in loops).Goffer
U
1

I would recommend that you set up getProfile to return an observable. Then your other functions can subscribe to that function and do their actions in the subscribe function. The Angular 2 HTTP tutorial gives an example of this

Utile answered 22/9, 2016 at 19:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.