【问题标题】:Avoid multiple ajax requests angularJS避免多个ajax请求
【发布时间】:2014-02-03 05:42:57
【问题描述】:

我试图避免对工厂中的服务器发出多个 ajax 请求。我已经添加了一个小的缓存服务,但是这还不够我的目标:在服务器响应之前,可以多次调用这个工厂,导致对服务器产生多个请求。

为了避免这种情况,我添加了第二个 promise 对象,如果 AJAX 请求已经执行并且对象尚未在缓存中,那么它应该等待第二个 promise 被解析,但看起来我错过了一些东西。

这是我的代码:

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

【问题讨论】:

  • 我在答案中添加了我的最终实现。

标签: angularjs promise q


【解决方案1】:

每次运行 getUser 时,都会为 firstRun 创建一个新的延迟。如果它已经运行,则调用 firstRun.then,但该承诺永远不会得到解决。

【讨论】:

  • 但是有什么方法可以实现我想要做的事情吗?
  • 在没有更多上下文的情况下无法告诉您。一次从一堆地方调用 GetUser?您可以在路由上使用 Resolve 以确保在开始执行操作之前已加载它。
  • 嗨@JonathanRowny 我用我自己的实现添加了一个答案,看看,让我知道你的想法。我接受了 smilledge 的回答,因为它看起来很干净。
【解决方案2】:

如果请求已经提出,您可以只返回原始承诺。像这样的东西应该可以工作;

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

【讨论】:

  • 感谢分享@smilledge。与此同时,当我问这个问题时,我自己实现了一些东西。但是,您的解决方案看起来非常干净紧凑,所以我接受了您的回答。看看我的,让我知道你的想法:)
【解决方案3】:

感谢大家的回答,同时我找到了一种缓存特定工厂的方法:

.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 数组,然后在请求准备好后解析整个队列,最后直接使用缓存值为每个未来请求解析promise。

我描述了这个promise caching here的实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 2013-12-21
    相关资源
    最近更新 更多