2014-01-14 3 views
5

Я пытаюсь избежать нескольких запросов ajax на сервере на заводе. Я уже добавил небольшую службу кеширования, но этого недостаточно для того, на что я нацелен: эту фабрику можно вызвать несколько раз, прежде чем сервер ответит, вызывая генерацию нескольких запросов на сервер.Избегайте нескольких запросов ajax angularJS

Чтобы избежать этого, я добавил второй объект обещания, который, если запрос AJAX был выполнен, и объект еще не находится в кеше, чем он должен ждать, пока второе обещание будет разрешено, но похоже, что я что-то не хватает ,

Это мой код:

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

Я добавил свою окончательную реализацию в ответы. –

ответ

6

Вы можете просто вернуть оригинальное обещание, если запрос уже сделан. Что-то вроде этого должно работать;

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

также посмотреть на Restangular documentation for caching requests

+0

Спасибо, что поделили @smilledge. Между тем с тех пор, как я задал вопрос, я кое-что реализовал сам. Однако ваше решение выглядит действительно чистым и компактным, поэтому я принял ваш ответ. Взгляните на меня и дайте мне знать, что вы думаете об этом :) –

0

Everytime запустить GetUser, новый Defer создан для FirstRun. Если он уже запущен, вы вызываете firstRun.then, но это обещание никогда не разрешается.

+0

Но есть ли способ достичь того, что я пытаюсь сделать? –

+0

Невозможно рассказать об этом без лишнего контекста. GetUser вызывается из нескольких мест сразу? Вы можете использовать Resolve на маршруте, чтобы убедиться, что он загружен, прежде чем начать что-то делать. –

+0

Привет @JonathanRowny Я добавил ответ с моей собственной реализацией, посмотрю и дайте мне знать, что вы думаете. Я согласился ответить на вопрос, потому что он выглядит действительно чистым. –

0

Спасибо всем за ответы, тем временем я нашел способ кэшировать этот конкретный завод:

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

     } 
    }; 
    } 
]); 

В принципе идея заключается в том, чтобы создать массив обещаний, в то время как userCache не готов, затем разрешите всю очередь, как только запрос будет готов, и, наконец, прямо разрешите обещание с кешированным значением для каждого будущего запроса.

Я описал реализацию этого promise caching here.

Смежные вопросы