Tengo una clase. Necesito hacer algún trabajo de http dentro de un tiempo de espera. El problema al que me enfrento es que la variable http dentro del tiempo de espera sigue diciendo que no está definida.
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 razón de esto es que la función de devolución de llamada dentro de setTimeout está en un entorno léxico diferente . Es por eso que en ES6+ las funciones se pueden definir usando => . Esto es para que el código dentro de una función comparta el mismo alcance que la función.
Para solucionar esto, puede usar la sintaxis ES6+, donde en lugar de function(a,b,args){...} usaría (a,b,args) => {...} :
setTimeout(() => { this.http.post(...); });o con sintaxis ES5:
var root = this; setTimeout(function(){ root.http.post(...); });¡Espero que esto ayude!
En JavaScript, la palabra clave this se usa para acceder al context en el que se invoca una función. Las funciones en JavaScript siempre se invocan con un contexto, ya sea que las invoque usando la sintaxis .methodName() o sin ella, a menos que el indicador 'use strict' esté establecido en el alcance actual.
Cuando se invoca una función sin un contexto como este:
myFunction() el tiempo de ejecución asume que el contexto es el objeto de ventana global (a menos que se establezca el indicador 'use strict' , en cuyo caso el contexto no estará definido).
Nota: cuando se utiliza ES6 con un transpilador como Babel, el modo estricto se establece de forma predeterminada en la salida.
Cuando se guarda una referencia a una función en un objeto, puede invocar esa función con el objeto como el contexto de 'esto' usando la sintaxis de punto.
var myObj = { myFunc: function(){} }; // myFunc invoked like this, the value of 'this' inside myFunc will be myObj. myObj.myFunc();Manipular 'esto':
Llame y aplique
Siempre puede cambiar el contexto de una función invocándola con los métodos .call o .apply. En este caso, tiene una función anónima que no invoca usted, sino que la invoca la función setTimeout. Por eso, no podrá aprovechar .call o .apply.
Unir
En su lugar, puede crear una nueva función que tenga un contexto personalizado utilizando el método .bind. Al invocar .bind() en su función anónima, se devolverá una nueva función que tiene su contexto personalizado vinculado a 'esto'. De esa manera, puede pasar su función enlazada personalizada como datos a setTimeout.
setTimeout(function(){ // your code. }.bind(this), 1000);ahora dentro de la función anónima, la palabra clave 'esto' estaría vinculada al valor correcto.
Léxico 'esto':
Sin embargo, en ES6, cuando se usa una función de flecha, las reglas sobre 'esto' cambian. Si usa esta sintaxis, verá que el contexto de 'esto' seguirá siendo el mismo que en el ámbito actual.
setTimeout(() => { // Hey I can access 'this' in here! }, 1000);Guardar una referencia:
Si observa la salida compilada de Babel, verá que Babel realiza un seguimiento del contexto al guardar las referencias a 'esto' con _esto1, _esto2, etc.
Para usar este método usted mismo, simplemente declare una nueva variable (es común usar 'eso' o 'yo') y acceda al valor usándolo dentro de su función anónima así:
var self = this; setTimeout(function(){ self.http.post... });Espero que esto ayude.
Para obtener más explicaciones, developer.mozilla.org tiene un buen artículo que describe el comportamiento de 'esto' dentro del alcance de una función .
Debe usar la función de flecha aquí, para preservar la existencia de esto.
setTimeout(()=>{ this.http.post(... //http is not defined here }) Al hacerlo, this interior de la función está ligado al contexto exterior. Es lo mismo que:
setTimeout(function(){ this.http.post(); }.bind(this));