延迟angular.js $ http服务

时间:2013-08-14 17:21:12

标签: angularjs angularjs-service

我有一些角色工厂,用于对传统的ASP.NET .asmx Web服务进行ajax调用,如下所示:

module.factory('productService', ["$http",
function ($http) {
    return {
        getSpecialProducts: function (data) {
            return $http.post('/ajax/Products.asmx/GetSpecialProducs', data);
        }
    }
} ]);

我正在本地网络上进行测试,因此响应时间“太”了。有没有一种聪明的方法可以将$ http延迟几秒钟来调用来模拟连接不良?

或者我是否需要在$ timeout中包含对工厂方法的所有调用?

$timeout(function() {
  productService.getSpecialProducs(data).success(success).error(error);
}, $scope.MOCK_ajaxDelay);

8 个答案:

答案 0 :(得分:53)

有趣的问题!

正如您自己提到的,$timeout是延迟通话的最合理选择。您可以推送一个响应拦截器,将$timeout承诺包含在$http承诺中,而不是$timeout概念中概述的$http承诺,并将其注册到您的一个配置块。这意味着所有$timeout次呼叫都会受到$httpProvider.interceptors.push(function($timeout) { return { "response": function (response) { return $timeout(function() { return response; }, 2500); } }; }); 延迟的影响。有点像:

{{1}}

作为“模拟连接错误?”的奖励,您可以随意拒绝或绝对做任何事情。 嘿嘿嘿嘿。

答案 1 :(得分:16)

新的Chrome设备模拟器具有网络限制功能:

enter image description here

要到达目的地:在Google Chrome中,按F12打开开发人员工具。然后,在左上角,单击"切换设备模式"图标(左边是"元素"菜单)。

答案 2 :(得分:4)

在@stevuu

的答案上进一步发展

responseInterceptors似乎已被弃用(截至1.2.20)我已修改代码以使用interceptors机制:

$httpProvider.interceptors.push(function($q, $timeout) {
    return {
        'response': function(response) {
            var defer = $q.defer();
            $timeout(function() {
                        defer.resolve(response);
                }, 2300);
            return defer.promise;
        }
    };
});

答案 3 :(得分:3)

您可以将$ q服务用于defer()。promise模式:

function someFunction(MOCK_ajaxDelay) {
   var deferred = $q.defer();
   $http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(function(response) {
      $timeout(function() {deferred.resolve({ success: true, response: response })}, MOCK_ajaxDelay);  
   }).error(function() {
      $timeout(function() {deferred.resolve({ success: true, response: response } }, MOCK_ajaxDelay);  
   });
   return deferred.promise;
}

someService.someFunction(500).then(function(data) {
    if (data.success) {
      $scope.items = data.response.d;
    }
});

但如果你真的是模拟测试,更好的解决方案是研究ngMock:http://docs.angularjs.org/api/ngMock。$ httpBackend

答案 4 :(得分:2)

虽然@stevuu's答案是正确的,但从那时起,新的AngularJS版本的语法已经改变。更新的语法是:

$httpProvider.interceptors.push(["$q", "$timeout", function ($q, $timeout) {
  function slower(response) {
    var deferred = $q.defer();
    $timeout(function() {
        deferred.resolve(response);
    }, 2000);
    return deferred.promise;
  }
  return {
    'response': slower
  };
}]);

答案 5 :(得分:0)

你可以使用promise api结合$ timeout来实现这一点。 $ http.post函数返回一个promise,您可以从中调用.success和.error(这些是特定于http的方法)。当http请求完成时,此承诺已解决。如果您构建自己的承诺,那么您可以告诉它延迟2秒,然后在http请求完成时解决:

module.factory('productService', function ($http, $q, $timeout) {

    return {
        getSpecialProducts: function (data) {
            var defer = $q.defer();
            $http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(
              function(data) {
                // successful http request, resolve after two seconds
                $timeout(function() {
                    defer.resolve(data);
                }, 2000)
            }).error(function() {
                defer.reject("Http Error");
            })
            return defer.promise;
        }
    }

});

但请注意 - 您必须使用promise.then(successCallback, errorCallback)功能 - 也就是说,您将失去访问http标头,状态和权限的功能。从控制器/指令配置,除非您明确地将它们提供给传递给defer.resolve({})

的对象

链接:

答案 6 :(得分:0)

为了回答您问题的测试方面,Fiddler有一个非常有用的功能,可以在您需要模拟延迟时提供帮助:

  1. 点击Fiddler中的AutoResponders标签。
  2. 添加一个规则,其中的正则表达式与您要延迟的请求的网址相匹配。
  3. 将“response with”设置为“* delay:1000”,其中数字是延迟(以毫秒为单位)。
  4. Fiddler中的AutoResponder功能对于测试涉及大量http请求的JS非常有用。您可以将其设置为使用特定的http错误代码,阻止响应等进行响应。

答案 7 :(得分:0)

如果您使用的是返回承诺的服务,那么您应该在 $ timeout 之前添加返回,因为这只会返回另一个承诺。

return dataService.loadSavedItem({
    save_id: item.save_id,
    context: item.context
}).then(function (data) {
    // timeout returns a promise
    return $timeout(function () {
        return data;
    },2000);
});

希望它有所帮助!