问题
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