81 votes

Javascript setInterval et la solution `this`

J'ai besoin d'accéder à this de mon setInterval handler

 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
        }
    }
 

Comment puis-je accéder à this.prefs dans ajax.onload ?

110voto

Nechehin Points 61
this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);

95voto

AnthonyWJones Points 122520

La ligne setInterval devrait ressembler à ceci: -

  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.
 ); 
 

Edit : Le même principe s’applique au " onload ". Dans ce cas, son code commun pour le code "externe" a peu d'effet, il configure simplement la demande et l'envoie ensuite. Dans ce cas, la surcharge supplémentaire liée à une fonction supplémentaire, comme dans le code ci-dessus, est inutile. Votre taux de récupération devrait ressembler davantage à ceci: -

 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);
}
 

19voto

Joel Fillmore Points 2594

Le comportement par défaut de setInterval est à lier au contexte mondial. Vous pouvez appeler une fonction membre par l'enregistrement d'une copie du contexte actuel. À l'intérieur de retrieve_rate l' this variable sera correctement lié au contexte d'origine. Voici à quoi ressemblerait le code:

var self = this;
this.intervalID = setInterval(
    function() { self.retrieve_rate(); },
    this.INTERVAL);

Bonus astuce: Pour une simple référence à une fonction (par opposition à un objet de référence qui a une fonction membre), vous pouvez modifier le contexte en utilisant du JavaScript call ou apply méthodes.

0voto

Matthew Flaschen Points 131723
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
        }
    }

-1voto

Crozin Points 22346

Ce n'est pas une solution de beauté mais son utilisation est courante:

 var self = this;
var ajax = null;
//...
ajax.onload = function() {
    self.prefs....;
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X