我有一些角色工厂,用于对传统的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);
答案 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设备模拟器具有网络限制功能:
要到达目的地:在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有一个非常有用的功能,可以在您需要模拟延迟时提供帮助:
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);
});
希望它有所帮助!