J'ai un cours. J'ai besoin de faire un travail http à l'intérieur d'un délai d'attente. Le problème auquel je suis confronté est que la variable http à l'intérieur du délai d'attente continue de dire qu'elle n'est pas définie.
export class MyClass {
http:Http:
constructor(private http:Http) {
this.http = http;
}
sendFriendRequest(){
this.http.post( ...//http variable is defined here
setTimeout(function(){
this.http.post(... //http is not defined here
}
}
}
La raison en est que la fonction de rappel à l'intérieur de setTimeout est dans un environnement lexical différent. C'est pourquoi dans ES6 + les fonctions peuvent être définies en utilisant =>
. C'est ainsi que le code dans une fonction partage la même portée que la fonction.
Pour résoudre ce problème, vous pouvez utiliser la syntaxe ES6 +, où au lieu de function(a,b,args) {...}
vous utiliseriez (a,b,args) => {...}
:
setTimeout( () => {
this.http.post(...)
});
ou avec la syntaxe ES5:
var root = this;
setTimeout(function(){
root.http.post(...)
}
J'espère que cela t'aides!
En JavaScript, le mot clé this
est utilisé pour accéder au context
dans lequel une fonction est invoquée. Les fonctions en JavaScript sont toujours appelées avec un contexte, que vous les appeliez à l'aide de la syntaxe .methodName()
ou sans, sauf si le 'use strict'
L'indicateur est défini dans la portée actuelle.
Lorsqu'une fonction est invoquée sans contexte comme celui-ci:
myFunction()
le contexte est supposé par le runtime être l'objet de fenêtre globale (sauf si le 'use strict'
L'indicateur est défini, auquel cas le contexte ne sera pas défini.)
Remarque: Lorsque vous utilisez ES6 avec un transpilateur comme Babel, le mode strict est défini par défaut dans la sortie.
Lorsqu'une référence à une fonction est enregistrée sur un objet, vous pouvez invoquer cette fonction avec l'objet comme contexte de "ceci" à l'aide de la syntaxe à points.
var myObj = {
myFunc: function(){}
};
// myFunc invoked like this, the value of 'this' inside myFunc will be myObj.
myObj.myFunc();
Manipulez 'ceci':
Appelez et postulez
Vous pouvez toujours modifier le contexte d'une fonction en l'invoquant avec les méthodes .call ou .apply. Dans ce cas, vous avez une fonction anonyme qui n'est pas appelée par vous, mais est plutôt invoquée par la fonction setTimeout. Pour cette raison, vous ne pourrez pas profiter de .call ou .apply.
Lier
Au lieu de cela, vous pouvez créer une nouvelle fonction qui a un contexte personnalisé à l'aide de la méthode .bind. En invoquant .bind () sur votre fonction anonyme, une nouvelle fonction sera retournée qui a votre contexte personnalisé lié à "ceci". De cette façon, vous pouvez passer votre fonction liée personnalisée en tant que données à setTimeout.
setTimeout(function(){
// your code.
}.bind(this), 1000);
maintenant à l'intérieur de la fonction anonyme, le mot-clé "this" serait lié à la valeur correcte.
Lexique 'ceci':
Cependant, dans ES6, lorsque vous utilisez une fonction de flèche , les règles concernant "ce" changement. Si vous utilisez cette syntaxe, vous verrez que le contexte de "ceci" restera le même que quoi que ce soit dans la portée actuelle.
setTimeout(() => {
// Hey I can access 'this' in here!
}, 1000);
Enregistrement d'une référence:
Si vous regardez la sortie compilée de Babel, vous verrez que Babel garde une trace du contexte en enregistrant les références à "this" avec _this1, _this2 et ainsi de suite.
Pour utiliser cette méthode vous-même, déclarez simplement une nouvelle variable (il est courant d'utiliser "ça" ou "moi") et accédez à la valeur en l'utilisant dans votre fonction anonyme comme ceci:
var self = this;
setTimeout(function(){
self.http.post...
});
J'espère que cela t'aides.
Pour plus d'explications, developer.mozilla.org a un bon article décrivant le comportement de 'this' dans une portée de fonctions .
Vous devez utiliser la fonction flèche ici, pour préserver son existence.
setTimeout(()=>{
this.http.post(... //http is not defined here
})
Ce faisant, this
à l'intérieur de la fonction est lié au contexte externe. C'est la même chose que:
setTimeout(function(){
this.http.post();
}.bind(this));
ce n'est pas le même this
à l'intérieur setTimeout
lorsque vous utilisez function(){...
2 façons les plus populaires pour ce problème:
1) utiliser une variable supplémentaire pour stocker en dehors de "ceci"
var that = this;
this.http.post( ...//http variable is defined here
setTimeout(function(){
that.http.post(... //http is not defined here
}
}
2) utiliser les fonctions fléchées
this.http.post( ...//http variable is defined here
setTimeout(() => {
that.http.post(... //http is not defined here
}
}
La première façon est l'ancienne ES5 et vous n'avez pas besoin de compilateurs, pour la version ES6 (# 2), vous devrez utiliser quelque chose comme babel.
en savoir plus sur les fonctions fléchées et babel ici: https://babeljs.io/docs/learn-es2015/