【问题标题】:AngularJS: timeout promise callsAngularJS:超时承诺调用
【发布时间】:2015-06-21 10:53:59
【问题描述】:

在我的AjaxPromiseService.js 工厂中,我一直在尝试将超时机制合并到promise 调用中(通常是$http.get/post 对远程服务的调用)。我目前正在做的方式是在 $timeout 事件和实际的承诺调用之间创建一个竞赛。示例代码如下(来自我的 AjaxPromiseService.js AngularJS 工厂的代码):also available in this plnkr

var timeoutObj = {"isTimeout": true};

function timeoutPromise(deferredObj) {
      $timeout(function() {
        console.log("promise timeout");
        deferredObj.resolve(timeoutObj);
        }, timeoutLimit); // timeoutLimit is in milisecond
    }

//promise calls (e.g. $http.get())
function getDummyData(milisec) {
      var data = {"data" : "dummy data from ajax!"};
      var deferred = $q.defer();

      timeoutPromise(deferred); //start the race to see who resolves first

      //use $timeout to mimick an AJAX call
      $timeout(function() {
        deferred.resolve(data);
        $timeout.cancel(timeoutPromise(deferred)); //not working, how to cancel the race here?
      }, milisec); //

      return deferred.promise;

    } //getDummyData

这似乎有效,如果getDummyData() 在指定的持续时间内没有解决,timeoutPromise() 将返回有用的标志,这样我就可以让 AJAX 调用优雅地失败。 timeoutPromise()getDummyData() 最终都会按顺序解决,但是,如果首先解决 getDummyData(),我想取消 timeoutPromise()。我想知道如何做到这一点?

【问题讨论】:

    标签: javascript ajax angularjs timeout promise


    【解决方案1】:

    根据$http documentation$http 配置的timeout 属性接受承诺,或者以毫秒为单位的数字

    timeout{number|Promise}以毫秒为单位的超时,或承诺在解决时应中止请求。

    因此解决方案很简单:

    function getData () {
        return $http.get(someUrl, {timeout: 3000});  // adjust the value to what you need
    }
    

    【讨论】:

      【解决方案2】:

      如果您使用 $http,则有一个更简单的选项。使用 $http 配置对象的 timeout 属性和 $timeout 服务:

      var requestTimeout = $timeout(function() {}, 4000);
      $http({ method:'GET', url:'...', timeout: requestTimeout});
      requestTimeout.then(function() {
         console.log ('request aborted - timed out!');
      });
      

      当请求在超时期限内成功时,$timeout 将自动中止。

      【讨论】:

        【解决方案3】:

        $http 有一个timeout 参数,当一个promise 被解决时请求超时——所以,你可以给它一个$timeoutpromise:

        getData: function(input, timeout){
          var timeoutPromise = timeout ? $timeout(function(){}, timeout) : null;
        
          return $http({url: "/some/url",
                        timeout: timeoutPromise,
                        method: "GET"
                       }).then(function(response){
                          var data = response.data;
                          // do something with data, if needed
                          return data;
                       });
        }
        

        DEMO

        【讨论】:

        • return $http().then() 返回一个承诺...我不确定你在问什么 - 一个承诺什么?
        • 所以你不需要在 $http() 中包装 $q.defer() 来返回一个承诺?
        • @TonyGW,当函数本身返回一个 Promise 时,很少会这样做,例如 $http$timeout 这样做......事实上,它会是一个 deferred anti-pattern
        • 但是在 timeoutPromise 中,如果我想返回一个带有标志 {isTimeout: true} 的 Promise 对象,是否需要 $q 来创建返回的 Promise?
        • timeoutPromise 在您的问题或我的回答中?你的意思是把它还给getData的用户吗?它将在哪里使用 - 在 Promise 处理程序中或由调用者使用?换句话说,我不完全理解你的新要求。我建议您编辑您的问题并进行澄清或创建一个新问题
        猜你喜欢
        • 2019-07-07
        • 2013-07-22
        • 2012-12-14
        • 1970-01-01
        • 1970-01-01
        • 2018-03-18
        • 2013-06-15
        • 1970-01-01
        • 2018-09-04
        相关资源
        最近更新 更多