延迟 angular.js $http 服务
Posted
技术标签:
【中文标题】延迟 angular.js $http 服务【英文标题】:Delay an angular.js $http service 【发布时间】:2013-08-16 18:56:06 【问题描述】:我有一些 angular factory 可以像这样对遗留的 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);
【问题讨论】:
【参考方案1】:有趣的问题!
正如您自己提到的,$timeout
是延迟通话最合乎逻辑的选择。您可以推送一个响应拦截器,该响应拦截器将$http
承诺包装在$timeout
承诺中,而不是到处都有$timeout
调用,正如documentation of $http
中概念性地概述的那样,并将其注册到您的配置块之一中。这意味着所有$http
调用都会受到$timeout
延迟的影响。大致如下:
$httpProvider.interceptors.push(function($timeout)
return
"response": function (response)
return $timeout(function()
return response;
, 2500);
;
);
作为“模拟不良连接?”的奖励,您也可以随机拒绝或完全不做任何事情。 嘿嘿嘿。
【讨论】:
胜过我的回答! - 似乎我需要阅读拦截器 如果服务器返回错误(即任何非 2XX),这将无法正常工作。在这种情况下,您还需要添加错误函数并拒绝它。 @cdmckay 当然你会处理失败的响应,但这不是问题的一部分;-)。 在哪里放置它的最佳位置,运行阶段还是配置阶段?好的,我自己回答:你不能把 $q 和 $timeout 放在配置阶段。嗯,真的吗?我放弃了…… 在较新的 AngularJS 版本中语法发生了变化。新语法为:***.com/a/31873453/232649【参考方案2】:新的chrome设备模拟器有网络节流功能:
要到达那里:在 Google Chrome 中,按 F12 打开开发者工具。然后,在左上角,点击“切换设备模式”图标(左侧的“元素”菜单)。
【讨论】:
在我的 Chrome 中,我在“网络”选项卡上找到了用于限制的下拉菜单。无需激活设备模拟器。 问题是,如果您正在模拟数据而不是实际进行网络调用,这将不起作用【参考方案3】:在@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;
;
);
【讨论】:
【参考方案4】:您可以将 $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
【讨论】:
【参考方案5】:虽然@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
;
]);
【讨论】:
【参考方案6】:您可以使用 promise api 和 $timeout 来实现这一点。 $http.post 函数返回一个promise,您可以从中调用.success 和.error(这些是http 特定的方法)。当 http 请求完成时,这个 promise resolved。如果您构建自己的 Promise,那么您可以告诉它延迟 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 标头、状态和配置,除非您明确将它们提供给传递给 @987654326 的对象@
链接:
Defer/Promise Api Http/Promise Api Resolve egghead video【讨论】:
【参考方案7】:针对您的问题的测试方面,Fiddler 有一个非常有用的功能,可以在您需要模拟延迟时提供帮助:
-
单击 Fiddler 中的“自动回复”选项卡。
使用与您要延迟的请求的 URL 匹配的正则表达式添加规则。
将“respond with”设置为“*delay:1000”,其中数字是以毫秒为单位的延迟。
Fiddler 中的 AutoResponder 功能对于测试涉及大量 http 请求的 JS 非常有用。您可以将其设置为响应特定的 http 错误代码、阻止响应等。
【讨论】:
我假设您使用的是 Windows,因为使用了 asp.net 网络服务。【参考方案8】:如果您正在使用返回承诺的服务,那么您也应该在 $timeout 之前放置一个 return,因为这只会返回另一个承诺。
return dataService.loadSavedItem(
save_id: item.save_id,
context: item.context
).then(function (data)
// timeout returns a promise
return $timeout(function ()
return data;
,2000);
);
希望它对某人有所帮助!
【讨论】:
以上是关于延迟 angular.js $http 服务的主要内容,如果未能解决你的问题,请参考以下文章
Yeoman Angular.js grunt serve-d 应用程序从 livereload.js?snipver=1 延迟很长