2014-01-14 2 views
5

공장에서 서버에 대한 여러 개의 ajax 요청을 피하려고합니다. 이미 작은 캐싱 서비스를 추가했지만 목표로는 충분하지 않습니다. 서버가 응답하기 전에이 팩토리를 여러 번 호출하여 여러 요청을 서버에 생성 할 수 있습니다.여러 Ajax 요청 방지하기 각도기

이 문제를 피하기 위해 AJAX 요청이 수행되고 개체가 아직 캐시되지 않은 경우 두 번째 약속이 해결 될 때까지 기다려야하지만 뭔가가 누락 된 것처럼 보이는 두 번째 약속 개체를 추가했습니다. . 당신이 인 getUser를 실행

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

요청이 이미 이루어진 경우 원래 약속을 반환 할 수 있습니다. 이 같은 것이 효과가있다.

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

     } 
    }; 
    } 
]); 

기본적으로 생각이 만드는 것입니다 :

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

매번 새로운 연기가 firstRun 생성됩니다 :

이 내 코드입니다. 이미 실행 중이면 firstRun.then을 호출하지만 그 약속은 결코 해결되지 않습니다.

+0

그러나 내가하려는 일을 성취 할 수있는 방법이 있습니까? –

+0

더 이상 문맥이 없으면 알려줄 수 없습니다. GetUser는 한 번에 여러 장소에서 호출되고 있습니까? 루트에서 Resolve를 사용하여 작업을 시작하기 전에로드되었는지 확인할 수 있습니다. –

+0

안녕하세요 @JonathanRowny 내 구현에 대한 답변을 추가하고 모양을 알려 주시고 내 생각을 알려주세요. 나는 그것이 정말로 깨끗해 보였기 때문에 벼 려서 대답으로 받아 들였다. –

0

감사를 보라 userCache이 준비되지 않은 동안 약속의 배열은 요청이 준비되면 전체 대기열을 해결하고 최종적으로 이후의 각 요청에 대해 캐시 된 값으로 약속을 직접 해결합니다.

이 구현의 설명은 promise caching here입니다.