AngularJS:使用超时属性

时间:2015-06-02 08:56:49

标签: javascript angularjs

我已经看过很多关于这个主题的帖子,以及很多网络文章,但我仍然对我的问题感到难过。我发现this post非常有用但我的timeoutRequest()函数永远不会被调用。

我使用的是具有$ http超时属性的promise,但是基础HTTP请求没有被取消。我认为承诺本身正在解决,但请求并未取消。

我的控制器行为如下所示:

$scope.enquiriesSelected = function() {
    $scope.cancelHttpRequests();
    $location.path("/enquiries");
};

$scope.cancelHttpRequests = function () {
    console.log(canceller.promise.$$state);
    canceller.resolve("User cancelled");
    console.log(canceller.promise.$$state);
};

我的HTTP请求承诺如下:

var canceller = $q.defer();

$scope.searchResultsPromise = $http({
        url: "/api/customers/customersearch",
        method: "POST",
        data: criteria,
        timeout: canceller.promise 
    })
    .success(function(data) {
        $scope.customerSearchResults = data;
    });

我尝试了各种方法来实现这一点,包括将取消器放在$ scope中。

我一直在查看AngularJS源代码,我发现这些行:

if (timeout > 0) {
    var timeoutId = $browserDefer(timeoutRequest, timeout);
} else if (isPromiseLike(timeout)) {
    timeout.then(timeoutRequest);
}

function timeoutRequest() {
    jsonpDone && jsonpDone();
    xhr && xhr.abort();
}

但是,当我的承诺得到解决时,执行路径无法到达这些行。永远不会调用xhr.abort(),这是AngularJS源代码中唯一中止HTTP请求的地方。

尝试取消请求时,使用F12(Chrome)中的控制台进行检查显示,promise的$$状态从0变为1,因此我可以合理地确定承诺正在解决。但是,在网络流量中,HTTP请求未被取消。在HTTP请求完成之前,我无法导航到另一个页面。

有人可以帮忙吗?

中号

1 个答案:

答案 0 :(得分:8)

您所描述的实际上是使用$http属性取消timeout请求的正确方法。我创建了this Plunkr,它表明此行为尽可能接近您提供的代码。您可以看到,当单击“提交请求超时”按钮时,将提交一个请求,并在100毫秒后解决超时承诺(因为请求返回得太快,以至于您没有时间点击某些内容取消它) :

$scope.requestWithTimeout = function() {
  $timeout(function(){canceller.resolve("User cancelled");}, 100);
  $scope.submitRequest();
}

$ http请求错误回调检查响应的状态并显示相应的错误消息,您可以在其中看到请求在100毫秒后实际取消。您还可以通过在浏览器的开发人员工具的网络选项卡中查看请求来验证这一点。

$scope.submitRequest = function() {
    // Reset the canceler promise
    canceller = $q.defer();
    $scope.status = 'Request submitted';
    var startTime = (new Date()).getTime();
    $http({ 
      url: 'style.css',
      method: 'GET',
      timeout: canceller.promise 
    })
    .success(function(data) {
      var endTime = (new Date()).getTime();
      $scope.status = 'Request response returned after ' + (endTime - startTime) + ' msec.';
    })
    .error(function(data, status) {
      var endTime = (new Date()).getTime();
      if(status === 0) {
        $scope.status = 'Request timed out after ' + (endTime - startTime) + ' msec.';
      } else {
        $scope.status = 'Request returned with error after ' + (endTime - startTime) + ' msec.';
      }
    });
  }

希望您可以将此作为示例来查找代码的错误并进行更正。否则请使用不起作用的代码创建一个Plunkr(或类似的东西),以便我可以进一步帮助您。