Trying to understand scope on angular 5 .then

可紊 提交于 2019-12-13 17:17:07

问题


On this example, the promise that i created works ok.

But the promise from the google api don't work.

It says that the this.youtube is undefined

index.html
<script src="https://apis.google.com/js/api.js"></script>

app.component.html

<button (click)="customClick()">custom Promise</button>
<hr>

<hello name="{{ youtube }}"></hello>
<button (click)="youtubeClick()">youtube Promise</button>

app.component.ts

import { Component } from '@angular/core';
import {  } from '@types/gapi.client.youtube';
import {  } from '@types/gapi.auth2';


export class AppComponent  {

  name = 'Angular 5';
  youtube = 'youtube';

  egPromise(){
    return new Promise<void>((resolve, reject) => {
      setTimeout(function(){
        resolve();
      }, 1000);
    });
  }

  customPromise(){
    this.egPromise().then( () => {
      this.name = 'from .then angular 5'
    });
  }

  customClick(){
    this.customPromise();
  }
/****************************************************/

youtubePromise(){
  gapi.client.init({
        apiKey: 'key',
        clientId: 'id',
        scope: "https://www.googleapis.com/auth/youtube.readonly",
        discoveryDocs: [
            "https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest"
        ]
        }).then(() => {
      this.youtube = 'from .then youtube'
    });
}

youtubeClick(){
  gapi.load('client:auth2', this.youtubePromise);
}

Edit: Solution/Explanation

With the help of @vivek-doshi

I found this post searching "bind this"

https://www.sitepoint.com/bind-javascripts-this-keyword-react/

And as the post explain

"it’s not always clear what this is going to refer to in your code, especially when dealing with callback functions, whose callsites you have no control over."

Since I'm working with the google API and i have no control over that code.

"This is because when the callback to the promise is called, the internal context of the function is changed and this references the wrong object."

And the function to load the library use a callback function, and don't even crossed my mind that the first callback was the problem.

So using the ES2015 Fat Arrows function, as the post says.

"they always use the value of this from the enclosing scope." ... "Regardless of how many levels of nesting you use, arrow functions will always have the correct context."

So instead of creating binding and self and that and wherever, I think that is more clean the use of =>

Other thing that it was confunsing me is that the google api aks for a callback with no argument.

So if you try to use const that = this; gapi.load('client:auth2', this.start(that) );

It will complain.

But using gapi.load('client:auth2', () => this.start() ); I'm not passing an argument.

This things could be simple for a lot of people, but since I'm learning, I will try to make it simple for others that are learning too.

Thanks everyone.


回答1:


Here you are losing the scope of this by calling :

gapi.load('client:auth2', this.youtubePromise);

Change above code to :

gapi.load('client:auth2', () => this.youtubePromise()); // ES6 Way
// OR
gapi.load('client:auth2', this.youtubePromise.bind(this)); // Traditional old way of doing

WORKING DEMO




回答2:


this is always the object the method is called on. However, when passing the method to then(), you are not calling it! The method will be stored somewhere and called from there later.

If you want to preserve this, you you need to preserve this before:

var that = this;
// ...
.then(function() { that.method() })


来源:https://stackoverflow.com/questions/49314827/trying-to-understand-scope-on-angular-5-then

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!