0

I'm trying to get data out of response but I can't seem to get the result I want.

facebookLogin(): void {

    this.fb.login()
        .then((res: LoginResponse) => {
            this.accessToken = res.authResponse.accessToken;
            this.expiresIn = res.authResponse.expiresIn;
            this.signedRequest = res.authResponse.signedRequest;
            this.userId = res.authResponse.userID;
            console.log('Logged In', res, this.accessToken); //works without problem 
            this.router.navigate(['../other-register']);
        })
        .catch(this.handleError);

    console.log(this.accessToken) //printing 'undefined'
}

Here within then => { }, console.log seems to print the data in res without any problem. I can see data I want but when I console.log outside of then =>{ }, it's giving me undefined.

what am I doing wrong? I need to use data inside response and pass them to other component but I can't seem to figure out what I'm doing wrong.

Can anyone help me? Thanks

Lea
  • 1,245
  • 5
  • 22
  • 31
  • 1
    You can pass data to other component from `then(){}` block itself. Since you are calling an asynchronous method, `console.log` outside `then` block will be executed before your `asynchronous` method returns. – Amit Chigadani Jun 07 '17 at 05:48
  • 1
    Possible duplicate of [How to return value from an asynchronous callback function?](https://stackoverflow.com/questions/6847697/how-to-return-value-from-an-asynchronous-callback-function) –  Jun 07 '17 at 07:17

1 Answers1

1

This is the expected behavior actually.

this.fb.login() is a Promise. This means that the value of the result/response (res) will not readily be available right when it is called, but it 'promises' that it will have a value once some action is taken or a response is returned and 'then' it will do something. In this case that action would be connecting to the Facebook API and having data returned. This is just like Ajax in jQuery if you have experience with that, Promises are a more evolved version of callbacks.

What is happening is that you function is being executed in this order:

  1. this.fb.login() is called. Doesn't have a value yet so it allows the script to continue.
  2. console.log() is called.
  3. this.fb.login's value is returned and the then() closure is executed.

If you want to know when the value is return or perform a specific action once it is returned you can call a function within .then() or look into observables (RxJS) to notify other parts of your application that login was successful (or wasn't).


Observables Example

Here is one example on Observables, however, I would do more research as there are multiple Subjects to select from, all which have slightly different behavior. Also, this kind of pattern works better in Angular2+ if this is performed in a service, that way other components will be able to access the information provided by Facebook.

import { AsyncSubject } from 'rxjs/AsyncSubject';

// ...

response: AsyncSubject<any> = new AsyncSubject();

facebookLogin(): void {

    this.fb.login()
        .then((res: LoginResponse) => {
            this.response.next(res);
            this.response.complete();
            this.router.navigate(['../other-register']);
        })
        .catch(this.handleError);

}

You then retrieve the data from within response like this:

this.response.subscribe(result => {
    console.log(result);
})

Pass Data Example

Since you already have a function in the service designed to receive the data, this may be a wiser implementation in your case.

facebookLogin(): void {

    this.fb.login()
        .then((res: LoginResponse) => {
            this.user_service.passData(res.authResponse.accessToken);
            this.router.navigate(['../other-register']);
        })
        .catch(this.handleError);

}
Jason Lemrond
  • 407
  • 2
  • 7
  • I tried this. this.response.subscribe(result => { this.user_service.passData( result.authResponse.accessToken); }) But service didn't get the data inside the 'result' response.. – Lea Jun 07 '17 at 05:10
  • I added another variation that might be easier to implement that doesn't require observables since you've already got a function designed to pass data. (See above). If you still want to use the Observable method, can you send me a large snipet to look at so I can see how it's all implemented. – Jason Lemrond Jun 07 '17 at 07:04