Javascript setInterval e `questa` soluzione

Ho bisogno di accedere this dal mio setInterval gestore

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

Come posso accedere a questo.preferenze nei ajax.onload ?

InformationsquelleAutor Pablo | 2010-05-01

 

9 Replies
  1. 85

    SetInterval linea dovrebbe assomigliare a questa:-

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

    Modifica: Lo stesso principio vale per il ” onload “. In questo caso il suo comune per la “esterno” codice per fare poco, imposta semplicemente la richiesta e poi invia. In questo caso l’overhead aggiuntivo di un aggiuntivo funzione nel codice di cui sopra è inutile. Il retrieve_rate dovrebbe essere più simile a questo:-

    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);
    }
    • Stavo per fare questo inizialmente, ma poi mi sono ricordato di questo modello è davvero molto più utile per i passanti.
    • Flaschen: È utile per questo scenario come per i passanti.
    • quindi il trucco con self è l’unica opzione? potete confermare che la soluzione di Matteo non funziona?
    • Prima di tutto, non è un “trucco” che il suo solo come funzionano le cose in Javascript. Matteo la risposta di come attualmente si trova al momento della stesura di questo commento non funziona. C’era una versione precedente che potrebbe aver funzionato, ma ha coinvolto passando this come un parametro che era inutile e awkard (qualsiasi chiamante di retrieve_rate sarebbe sapere questo non è più necessario il requisito speciale).
    • passando this come argomento per il (function(self){...})(this) in setInterval non ha funzionato per me, perché la funzione viene eseguita immediatamente, invece di essere in ritardo. @Joel Fillmore soluzione funziona per me
    • Vorrei che avevo conosciuto circa 12 ore fa. In modo permanente etch nel mio cervello ora. Grazie!
    • Impressionante l’uomo! Salva la giornata
    • Se si sta utilizzando Underscore.js, è possibile utilizzare _.bind che fa per voi: this.intervalID = setInterval(_.bind(this.retrieve_rate, this), this.INTERVAL);
    • Che è un sacco di staffe c’

  2. 76
    this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);
    • Questa è la soluzione giusta. L’unica soluzione sembra essere inutilmente il codice più.
    • Ma questo metodo ha un inconveniente. Molto probabilmente, non funziona con le vecchie versioni di IE
    • Degno di nota. Ma la sua ancora un altro cleaner soluzione.
    • E ‘ supportato da IE9 quindi è una soluzione pulita per me.
    • Se avete bisogno di supporto per IE8 e stai utilizzando Underscore.js, è possibile utilizzare _.bind: this.intervalID = setInterval(_.bind(this.retrieve_rate, this), this.INTERVAL);
  3. 18

    Il comportamento predefinito di setInterval è quello di associare il contesto globale. È possibile chiamare una funzione membro di salvare una copia dell’attuale contesto. All’interno retrieve_rate il this variabile sarà associato correttamente il contesto originale. Qui è che cosa il vostro codice sarà simile a:

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

    Bonus suggerimento: Per una normale funzione di riferimento (rispetto a un riferimento a un oggetto che ha una funzione membro) si può cambiare il contesto utilizzando JavaScript call o apply metodi.

    • Questo ha funzionato per me, la chiamata alla ‘chiamata’ non sembra essere comunque necessaria. Il contesto di retrieve_rate dovrebbe essere impostata su automatica per impostazione predefinita, perché si chiama come una funzione membro.
    • hai ragione, mi sono ricordato che la risoluzione di questo per una funzione di callback di riferimento dove è stato necessario. Ho corretto la risposta, grazie!
  4. 11

    Con il miglioramento di supporto del browser, adesso è il momento buono per utilizzare il EcmaScript 6 valorizzazione, la freccia => metodo, per preservare this correttamente.

    startup : function()
        {
            //init prefs
            ...
            this.retrieve_rate();
            this.intervalID = setInterval( () => this.retrieve_rate(), this.INTERVAL);
        },

    Usare => metodo consente di mantenere la this quando retrieve_rate() è chiamato dall’intervallo. Nessun bisogno di funky auto o di passaggio this nei parametri

  5. 7

    window.setInterval(function(){console.log(this)}.bind(this), 100)

    questo è legale in javascript e consente di risparmiare un sacco di codice 🙂

  6. 2

    Questa sarebbe la soluzione più pulita, poiché la maggior parte del tempo che effettivamente desidera passare questo contesto per la tua consecutivi chiamate di metodo:

    Inoltre, è più facile cogliere il concetto di.

        //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);
    • Ha funzionato per me chiamando that.myMethod()
  7. 0
    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 all’interno della funzione passati a setInterval, farà riferimento all’oggetto globale. Volevi dire context.retrieve_rate invece di this.retrieve_rate ?
    • Grazie per la macchia che, CMS.
    • Questo si è evoluto nella direzione giusta, non è necessario il contesto viene passato come parametro, però.
    • Antonio allora, come faccio ad accedere da onload? Provato questo.preferenze, ma non ha funzionato…
    • Sei il benvenuto Matteo, a proposito, non hai bisogno di utilizzare call, context.retrieve_rate() è sufficiente, dal momento che si dispone di un oggetto di base (context.)
    • Grazie ancora, @Antonio e @CMS. 🙂 È facile da ottenere inutilmente “intelligente” quando le chiusure sono in gioco.
    • Non potevo accedervi né con this né con context… Se si sa esattamente come, si prega di aggiornare il codice di accesso.
    • dovrebbe funzionare in onload. Mi consiglia di utilizzare una libreria di supporto AJAX (come jQuery), però.

  8. 0

    Con i browser più moderni il metodo setInterval, altri parametri che vengono passati alla funzione specificata dal func una volta che il timer scade.

    var intervalID = portata.setInterval(func, ritardo[, param1, param2, …]);

    Quindi, una possibile soluzione può essere:

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

    Una demo:

    JS:

    var timerId;
    document.querySelector('#clickMe').addEventListener('click', function(e) {
        timerId = setInterval(function (self) {
            self.textContent = self.textContent.slice(0, -1);
            if (self.textContent.length == 0) {
                clearInterval(timerId);
                self.textContent = 'end..';
            }
        }, 250, this);
    })

    HTML:

    <button id="clickMe">ClickMe</button>

  9. -1

    Che non è una bellezza soluzione, ma nell’uso comune:

    var self = this;
    var ajax = null;
    //...
    ajax.onload = function() {
        self.prefs....;
    }
    • Il problema è come setInterval chiama il retrieve_rate funzione, il this valore all’interno del metodo si riferisce all’oggetto globale…

Lascia un commento