For 体验: 很多时候,请求后台接口比较慢,还在等待返回。如果此时用户选择了切换页面,这时候我们可以选择将还在进行中的请求主动中断。
jQuery
//可以在通用的入口abort()掉request
var request = $.ajax({
type: 'POST',
url: 'someurl',
success: function(result){}
});
request.abort();
Angular1.x
angular.module('app.services', [])
// 发送中的请求
.factory('PendingRequests', [
function(){
var list = []; // 私有变量
return {
push: function(canceller){
list.push(canceller);
},
remove: function(canceller){
var index = _.indexOf(list, canceller);
if (index > -1) {
list.splice(index, 1);
}
},
clear: function(){
_.forEach(list, function(item){
item.resolve();
});
list = [];
}
};
}
])
// 请求包装
.factory('RequestWrapper', [
'$q', '$http', 'PendingRequests',
function($q , $http , PendingRequests){
function wrapper(type, config, options){
// 自动中断的canceller
var canceller;
// 主动传入 `timeout` 不自动中断
if (!config.hasOwnProperty('timeout')) {
canceller = $q.defer();
config.timeout = canceller.promise;
}
var req = $http(config);
if (canceller) {
PendingRequests.push(canceller);
}
var defer = $q.defer();
req.then(function(res){
var match = type === 'array' ?
angular.isArray(res.data) :
angular.isObject(res.data) && !angular.isArray(res.data);
if (match) {
defer.resolve(res.data);
} else {
res.TypeError = true;
defer.reject(res);
}
}, function(res){
defer.reject(res);
if (res.status === 0) {
// 请求主动中断
return;
}
});
if (canceller) {
// 请求已完成,从 pending 中移除
req['finally'](function(){
PendingRequests.remove(canceller);
});
}
return defer.promise;
}
// array 或 object 两种返回
return {
array: function(req, options){
return wrapper('array', req, options);
},
object: function(req, options){
return wrapper('object', req, options);
}
};
}
])