Le fabbriche "lazy loading" in AngularJS utilizzano questa buona pratica del metodo $ q.defer

1

Credo di non credere in me stesso come un buon programmatore, ma ho scoperto questo metodo da solo (non suggerisco di essere il primo a farlo, ma non ho seguito una guida), quindi deve essere rotto in qualche modo.

$ q è principalmente un tipo di servizio di callback per ragioni asincrone, ma mi è servito anche in un altro modo.

Potrei avere più chiamate a un servizio di lunga durata, ma ho solo bisogno di una risposta una volta. Quindi voglio ignorare tutte le chiamate tranne dal primo e memorizzare il risultato in cache e tornare a tutti.

Se faccio una promessa a tutti quando ricevono il risultato quando la promessa è risolta, anche se è stata risolta prima che la promessa sia effettivamente data, questa è una bella caratteristica.

Quindi ho potuto fare la chiamata al dervice solo la prima volta che ho dato la promessa.

myApp.factory('serviceWithLongCall', function ($q, $timeout) {

    var data = {}
    var hasStarted = false;
    var deferred = $q.defer();

    return {
        call: call
    };

    function call() {
        if (!hasStarted) {
            hasStarted = true;
            console.log('timeout started');
            $timeout(function () {
                console.log('timeout ended');
                data = 42;
                deferred.resolve(data);
            }, 3000);
        }

        return deferred.promise;
    }

});

fiddle con esempio, fai clic su alcuni pulsanti e attendi 3 secondi dal primo clic, i clic successivi si verificheranno istantaneamente.

Qualcosa non funziona con questo metodo, avrò una condizione di gara?

    
posta Ingó Vals 12.06.2015 - 16:20
fonte

1 risposta

1

Restituire la stessa promessa da una chiamata più volte per motivi di memorizzazione nella cache è assolutamente soddisfacente. Nessuna condizione di gara a cui possa pensare, e ho usato quella tecnica senza problemi.

L'unico piccolo problema con il tuo codice è che non è necessario creare l'oggetto posticipato. $timeout restituisce una promessa che può risolvere il valore desiderato.

myApp.factory('serviceWithLongCall', function ($timeout) {

    var data = {}
    var promise = null;

    return {
        call: call
    };

    function call() {
        if (!promise) {
            console.log('timeout started');
            promise = $timeout(function () {
                console.log('timeout ended');
                data = 42;
                return data;
            }, 3000);
        }

        return promise;
    }
});

Certamente il tuo uso di $timeout potrebbe essere solo per motivi di esempio, ma sospetto che tu possa fare la stessa cosa con $http .

    
risposta data 14.06.2015 - 00:10
fonte

Leggi altre domande sui tag