I have some angular factories for making ajax calls towards legacy ASP.NET .asmx web services like so:
我有一些用于对遗留ASP进行ajax调用的有棱角的工厂。NET .asmx web服务如下:
module.factory('productService', ["$http",
function ($http) {
return {
getSpecialProducts: function (data) {
return $http.post('/ajax/Products.asmx/GetSpecialProducs', data);
}
}
} ]);
I'm testing on a local network so response times are "too" good. Is there a smart way of delaying the $http a couple of seconds from making the call to simulate a bad connection?
我正在本地网络上测试,所以响应时间“太”好了。是否有一种聪明的方法可以将$http延迟几秒钟,使其不能进行模拟错误连接的调用?
Or do I need to wrap all calls to the factory methods in a $timeout ?
还是需要在$timeout中包装所有对工厂方法的调用?
$timeout(function() {
productService.getSpecialProducs(data).success(success).error(error);
}, $scope.MOCK_ajaxDelay);
8 个解决方案
#1
50
Interesting question!
有趣的问题!
As you mentioned yourself, $timeout
is the most logical choice for a delayed call. Instead of having $timeout
calls everywhere, you could push a response interceptor that wraps the $http
promise in a $timeout
promise, as conceptually outlined in the documentation of $http
, and register it in one of your configuration blocks. This means all $http
calls are affected by the $timeout
delay. Something along the lines of:
正如您自己提到的,对于延迟调用,$timeout是最合理的选择。不需要到处都有$timeout调用,您可以推一个响应拦截器,它将$http承诺包装为$timeout承诺,就像$http文档中概念上描述的那样,并将其注册到您的一个配置块中。这意味着所有$http调用都受到$timeout延迟的影响。类似于:
$httpProvider.interceptors.push(function($timeout) {
return {
"response": function (response) {
return $timeout(function() {
return response;
}, 2500);
}
};
});
As a bonus to your "to simulate a bad connection?", you could reject or do absolutely nothing randomly, too. Heh heh heh.
作为你的“模拟错误连接”的奖励?,你也可以拒绝,也可以什么都不做。呵呵呵。
#2
16
The new chrome device emulator has a network throttling function:
新的chrome设备模拟器具有网络节流功能:
To get there: In Google Chrome, press F12 to open the Developer Tools. Then, on the top left corner, click the "Toggle device mode" icon (left to the "Elements" menu).
要达到目标:在谷歌Chrome中,按F12打开开发工具。然后,在左上角,点击“切换设备模式”图标(左至“元素”菜单)。
#3
4
Developing more on the answer of @stevuu
开发更多关于@stevuu的答案
responseInterceptors
seems to be depreceted (as of 1.2.20) I have modified the code to work on the interceptors
mechanism:
responseInterceptors似乎被排在前面(从1.2.20开始),我已经修改了代码来处理拦截器机制:
$httpProvider.interceptors.push(function($q, $timeout) {
return {
'response': function(response) {
var defer = $q.defer();
$timeout(function() {
defer.resolve(response);
}, 2300);
return defer.promise;
}
};
});
#4
3
You could use the $q service for defer().promise pattern:
您可以使用$q服务来延迟()。承诺模式:
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;
}
});
But if you are really mock testing, the better solution is to look into ngMock: http://docs.angularjs.org/api/ngMock.$httpBackend
但是,如果您真的是模拟测试,那么更好的解决方案是查看ngMock: http://docs.angularjs.org/api/ngMock, $ http后端。
#5
2
While @stevuu's answer is correct, the syntax has changed in the newer AngularJS versions since then. The updated syntax is:
虽然@stevuu的答案是正确的,但是从那时起,新的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
0
You can achieve this using the promise api combined with a $timeout. The $http.post function returns a promise from which you can call .success and .error (these are http specific methods). This promise is resolved when the http request is complete. If you build your own promise then you can tell it to delay 2 seconds and then resolve when the http request is complete:
您可以使用promise api和$timeout实现此功能。美元的http。post函数返回一个承诺,您可以从中调用.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;
}
}
});
But note - you will have to use promise.then(successCallback, errorCallback)
functionality - that is, you'll lose the ability to access http headers, status & config from your controllers/directives unless you explicitly supply them to the object passed to defer.resolve({})
但是注意——你必须使用承诺。然后(成功地返回,errorCallback)功能——也就是说,您将失去从控制器/指令访问http头、状态和配置的能力,除非您显式地将其提供给传递给延迟的对象。
Links:
链接:
- Defer/Promise Api
- 推迟/承诺Api
- Http/Promise Api
- Http /承诺Api
- Resolve egghead video
- 解决书呆子视频
#7
0
In response to the testing aspect of your question, Fiddler has a really useful function that helps when you need to simulate delays:
针对您的问题的测试方面,Fiddler有一个非常有用的功能,当您需要模拟延迟时,它可以帮助您:
- Click on the AutoResponders tab in Fiddler.
- 单击Fiddler中的AutoResponders选项卡。
- Add a rule with a regex that matches the URL of the request you want to delay.
- 添加一条规则,该规则与要延迟的请求的URL匹配。
- Set the "respond with" to "*delay:1000" where the number is the delay in milliseconds.
- 设置“response with”to“*delay:1000”,其中数字为毫秒的延迟。
The AutoResponder functionality in Fiddler is extremely useful for testing JS that involves a lot of http requests. You can set it to respond with particular http error codes, block responses, etc.
Fiddler中的AutoResponder功能对于测试包含大量http请求的JS非常有用。您可以设置它以响应特定的http错误代码、块响应等。
#8
0
If you are using a service that returns a promise, then inside you should put a return before the $timeout as well because that returns just another promise.
如果您正在使用一个返回承诺的服务,那么您应该在$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);
});
Hope it helps someone!
希望它能帮助一些人!
#1
50
Interesting question!
有趣的问题!
As you mentioned yourself, $timeout
is the most logical choice for a delayed call. Instead of having $timeout
calls everywhere, you could push a response interceptor that wraps the $http
promise in a $timeout
promise, as conceptually outlined in the documentation of $http
, and register it in one of your configuration blocks. This means all $http
calls are affected by the $timeout
delay. Something along the lines of:
正如您自己提到的,对于延迟调用,$timeout是最合理的选择。不需要到处都有$timeout调用,您可以推一个响应拦截器,它将$http承诺包装为$timeout承诺,就像$http文档中概念上描述的那样,并将其注册到您的一个配置块中。这意味着所有$http调用都受到$timeout延迟的影响。类似于:
$httpProvider.interceptors.push(function($timeout) {
return {
"response": function (response) {
return $timeout(function() {
return response;
}, 2500);
}
};
});
As a bonus to your "to simulate a bad connection?", you could reject or do absolutely nothing randomly, too. Heh heh heh.
作为你的“模拟错误连接”的奖励?,你也可以拒绝,也可以什么都不做。呵呵呵。
#2
16
The new chrome device emulator has a network throttling function:
新的chrome设备模拟器具有网络节流功能:
To get there: In Google Chrome, press F12 to open the Developer Tools. Then, on the top left corner, click the "Toggle device mode" icon (left to the "Elements" menu).
要达到目标:在谷歌Chrome中,按F12打开开发工具。然后,在左上角,点击“切换设备模式”图标(左至“元素”菜单)。
#3
4
Developing more on the answer of @stevuu
开发更多关于@stevuu的答案
responseInterceptors
seems to be depreceted (as of 1.2.20) I have modified the code to work on the interceptors
mechanism:
responseInterceptors似乎被排在前面(从1.2.20开始),我已经修改了代码来处理拦截器机制:
$httpProvider.interceptors.push(function($q, $timeout) {
return {
'response': function(response) {
var defer = $q.defer();
$timeout(function() {
defer.resolve(response);
}, 2300);
return defer.promise;
}
};
});
#4
3
You could use the $q service for defer().promise pattern:
您可以使用$q服务来延迟()。承诺模式:
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;
}
});
But if you are really mock testing, the better solution is to look into ngMock: http://docs.angularjs.org/api/ngMock.$httpBackend
但是,如果您真的是模拟测试,那么更好的解决方案是查看ngMock: http://docs.angularjs.org/api/ngMock, $ http后端。
#5
2
While @stevuu's answer is correct, the syntax has changed in the newer AngularJS versions since then. The updated syntax is:
虽然@stevuu的答案是正确的,但是从那时起,新的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
0
You can achieve this using the promise api combined with a $timeout. The $http.post function returns a promise from which you can call .success and .error (these are http specific methods). This promise is resolved when the http request is complete. If you build your own promise then you can tell it to delay 2 seconds and then resolve when the http request is complete:
您可以使用promise api和$timeout实现此功能。美元的http。post函数返回一个承诺,您可以从中调用.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;
}
}
});
But note - you will have to use promise.then(successCallback, errorCallback)
functionality - that is, you'll lose the ability to access http headers, status & config from your controllers/directives unless you explicitly supply them to the object passed to defer.resolve({})
但是注意——你必须使用承诺。然后(成功地返回,errorCallback)功能——也就是说,您将失去从控制器/指令访问http头、状态和配置的能力,除非您显式地将其提供给传递给延迟的对象。
Links:
链接:
- Defer/Promise Api
- 推迟/承诺Api
- Http/Promise Api
- Http /承诺Api
- Resolve egghead video
- 解决书呆子视频
#7
0
In response to the testing aspect of your question, Fiddler has a really useful function that helps when you need to simulate delays:
针对您的问题的测试方面,Fiddler有一个非常有用的功能,当您需要模拟延迟时,它可以帮助您:
- Click on the AutoResponders tab in Fiddler.
- 单击Fiddler中的AutoResponders选项卡。
- Add a rule with a regex that matches the URL of the request you want to delay.
- 添加一条规则,该规则与要延迟的请求的URL匹配。
- Set the "respond with" to "*delay:1000" where the number is the delay in milliseconds.
- 设置“response with”to“*delay:1000”,其中数字为毫秒的延迟。
The AutoResponder functionality in Fiddler is extremely useful for testing JS that involves a lot of http requests. You can set it to respond with particular http error codes, block responses, etc.
Fiddler中的AutoResponder功能对于测试包含大量http请求的JS非常有用。您可以设置它以响应特定的http错误代码、块响应等。
#8
0
If you are using a service that returns a promise, then inside you should put a return before the $timeout as well because that returns just another promise.
如果您正在使用一个返回承诺的服务,那么您应该在$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);
});
Hope it helps someone!
希望它能帮助一些人!