2014-01-14 5 views
5

Ich versuche, mehrere AJAX-Anfragen an den Server in einer Fabrik zu vermeiden. Ich habe bereits einen kleinen Caching-Dienst hinzugefügt, aber es ist nicht genug für das, was ich anstrebe: Diese Fabrik kann mehrere Male aufgerufen werden, bevor der Server antwortet, was die Erzeugung mehrerer Anfragen an den Server verursacht.Vermeiden Sie mehrere AJAX-Anfragen angularJS

Um dies zu vermeiden, fügte ich ein zweites Versprechen Objekt, die, wenn die AJAX-Anfrage durchgeführt wurden und das Objekt noch nicht im Cache ist, als es warten sollte, bis eine zweite Versprechen gelöst wird, aber sieht aus wie ich etwas fehlt .

Dies ist mein Code:

myApp.factory('User', ['Restangular', '$q', 
    function (Restangular, $q) { 
    var userCache, alreadyRun = false; 
    return { 
     getUser: function() { 
     var deferred = $q.defer(), firstRun= $q.defer(); 

     if (!userCache && !alreadyRun) { 
      alreadyRun = true; 

      Restangular.all('user').getList().then(function (user) { 
      console.log('getting user live '); 
      userCache = user[0].email; 
      firstRun.resolve(user[0].email); 
      }); 
     } else if (!userCache && alreadyRun) { 
      console.log('waiting for the first promise to be resolved '); 
      firstRun.then(function(user) { 
      console.log('resolving the promise'); 
      deferred.resolve(userCache); 
      }); 

     } else { 
      console.log('resolving the promise from the cache'); 
      deferred.resolve(userCache) 
     } 
     return deferred.promise; 
     } 
    }; 
    } 
]); 
+0

Ich habe meine endgültige Implementierung in den Antworten hinzugefügt. –

Antwort

6

Sie könnten einfach das ursprüngliche Versprechen zurückgeben, wenn die Anfrage bereits erfolgt ist. So etwas sollte funktionieren;

myApp.factory('User', ['Restangular', '$q', 
    function (Restangular, $q) { 
    var deferred = false; 

    return { 
     getUser: function() { 

     if(deferred) { 
      return deferred.promise; 
     } 

     deferred = $q.defer(); 

     Restangular.all('user').getList().then(function (user) { 
      deferred.resolve(user[0].email); 
     }); 

     return deferred.promise; 
     } 
    }; 
    } 
]); 

haben auch einen Blick auf den Restangular documentation for caching requests

+0

Danke, dass Sie @smilledge teilen. In der Zwischenzeit, als ich die Frage gestellt habe, habe ich etwas selbst umgesetzt. Aber Ihre Lösung sieht wirklich sauber und kompakt aus, also habe ich Ihre Antwort akzeptiert. Schau dir meine an und lass mich wissen, was du davon hältst :) –

0

Jedesmal, wenn man getUser laufen, ein neues Zurückstellungs für FirstRun erstellt wird. Wenn es bereits ausgeführt wird, rufen Sie firstRun.then auf, aber dieses Versprechen wird nie gelöst.

+0

Aber es gibt einen Weg zu erreichen, was ich versuche zu tun? –

+0

Kann ich dir nicht ohne mehr Kontext sagen. GetUser wird von mehreren Orten gleichzeitig aufgerufen? Sie können die Option Auf einer Route auflösen auswählen, um sicherzustellen, dass sie geladen ist, bevor Sie mit der Ausführung beginnen. –

+0

Hallo @ JonathanRowny Ich habe eine Antwort mit meiner eigenen Implementierung hinzugefügt, schau sie dir an und lass mich wissen, was du denkst. Ich habe die Antwort als Antwort akzeptiert, weil sie sehr sauber aussieht. –

0

Dank alle für die Antworten, in der Zwischenzeit ich einen Weg gefunden, dass bestimmte Fabrik cachen:

.factory('User', ['Restangular', '$q', 
    function (Restangular, $q) { 
    var userCache, promises = []; 
    return { 

     getUser: function() { 

     var deferred = $q.defer(); 

     if (promises.length > 0) { 

      promises.push(deferred); 

     } else if (!userCache) { 

      promises.push(deferred); 

      Restangular.all('user').getList().then(function (user) { 
      var i; 
      userCache = user[0]; 
      for (i = promises.length; i--;) { 
       promises.shift().resolve(userCache); 
      } 
      }); 

     } else { 

      deferred.resolve(userCache); 

     } 

     return deferred.promise; 

     } 
    }; 
    } 
]); 

Grundsätzlich ist die Idee zu schaffen eine Reihe von Versprechen, während userCache ist nicht bereit, dann lösen Sie die gesamte Warteschlange, sobald die Anfrage bereit ist und schließlich lösen Sie die Versprechen mit dem zwischengespeicherten Wert für jede zukünftige Anfrage.

Ich beschrieb die Implementierung dieser promise caching here.

Verwandte Themen