javascript - español - setinterval react
Javascript setInterval y la solución `this` (8)
Necesito acceder a this
desde mi controlador setInterval
prefs: null,
startup : function()
{
// init prefs
...
this.retrieve_rate();
this.intervalID = setInterval(this.retrieve_rate, this.INTERVAL);
},
retrieve_rate : function()
{
var ajax = null;
ajax = new XMLHttpRequest();
ajax.open(''GET'', ''http://xyz.com'', true);
ajax.onload = function()
{
// access prefs here
}
}
¿Cómo puedo acceder a this.prefs en ajax.onload
?
Con la mejora de la compatibilidad con el navegador, ahora es el momento de usar la mejora EcmaScript 6, el método arrow =>
, para preservarlo adecuadamente.
startup : function()
{
// init prefs
...
this.retrieve_rate();
this.intervalID = setInterval( () => this.retrieve_rate(), this.INTERVAL);
},
El método => conserva this
cuando el intervalo llama a retrieve_rate()
. No es necesario funky self o pasar this
en parámetros
El comportamiento predeterminado de setInterval
es vincularse al contexto global. Puede llamar a una función miembro guardando una copia del contexto actual. Dentro de retrieve_rate, this
variable se vinculará correctamente con el contexto original. Así es como se vería tu código:
var self = this;
this.intervalID = setInterval(
function() { self.retrieve_rate(); },
this.INTERVAL);
Consejo de bonificación: para una referencia de función simple (a diferencia de una referencia de objeto que tiene una función de miembro) puede cambiar el contexto utilizando la call
de JavaScript o apply
métodos.
Esa no es una solución de belleza, pero es de uso común:
var self = this;
var ajax = null;
//...
ajax.onload = function() {
self.prefs....;
}
Esta sería la solución más limpia, ya que la mayoría de las veces realmente desea cambiar el contexto para sus llamadas a métodos consecutivos:
También es más fácil comprender el concepto de.
// store scope reference for our delegating method
var that = this;
setInterval(function() {
// this would be changed here because of method scope,
// but we still have a reference to that
OURMETHODNAME.call(that);
}, 200);
La línea setInterval debería verse así: -
this.intervalID = setInterval(
(function(self) { //Self-executing func which takes ''this'' as self
return function() { //Return a function in the context of ''self''
self.retrieve_rate(); //Thing you wanted to run as non-window ''this''
}
})(this),
this.INTERVAL //normal interval, ''this'' scope not impacted here.
);
Editar : el mismo principio se aplica a la " onload
". En este caso es común que el código "externo" haga poco, simplemente configura la solicitud y luego la envía. En este caso, la sobrecarga adicional es innecesaria una función adicional como en el código anterior. Su retrieve_rate debería verse más como esto: -
retrieve_rate : function()
{
var self = this;
var ajax = new XMLHttpRequest();
ajax.open(''GET'', ''http://xyz.com'', true);
ajax.onreadystatechanged= function()
{
if (ajax.readyState == 4 && ajax.status == 200)
{
// prefs available as self.prefs
}
}
ajax.send(null);
}
window.setInterval(function(){console.log(this)}.bind(this), 100)
esto es legal en JavaScript y ahorra un montón de código :)
prefs: null,
startup : function()
{
// init prefs
...
this.retrieve_rate();
var context = this;
this.intervalID = setInterval(function()
{
context.retrieve_rate();
}, this.INTERVAL);
},
retrieve_rate : function()
{
var ajax = null;
ajax = new XMLHttpRequest();
ajax.open(''GET'', ''http://xyz.com'', true);
var context = this;
ajax.onload = function()
{
// access prefs using context.
// e.g. context.prefs
}
}
this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);