我正在努力提高我在具有滞后网络的移动设备上的应用性能。
第一步是为所有http请求添加“全局”超时,我使用了简单的request
拦截器 - request(config) { return angular.extend({ timeout: 30000 }, config) }
。它工作正常 - 而不是无限等待响应我可以显示关于滞后网络的警告(在responseError
拦截器中),此外慢速请求被取消所以我可以预期它应该为其他请求释放一些带宽
现在我正在尝试实现另一个优化 - 在uiRouter状态更改之前取消挂起的http请求,因为没有理由为不再显示的状态加载资源。例如,当用户试图导航到状态A时,A resolvables正在等待,无聊的用户改变了主意,他正试图导航到状态B.
我目前的实施基于$q
和$timeout
服务和自定义服务,用于收集所有http请求的超时,并在必要时批量取消它们。够了,这是代码:
const REQUEST_TIMEOUT = 3000; // 30 secs
function httpRequestsCancellerService($timeout, $transitions, $q) {
const cancelers = [];
function cancelAll() {
while (cancelers.length > 0) {
const canceler = cancelers.pop();
canceler.resolve();
}
}
// Cancel all pending http requests before the next transition
$transitions.onStart({}, cancelAll);
return {
createTimeout() {
const canceler = $q.defer();
// TODO it will keep running even whe the request is completed or failed
$timeout(canceler.resolve, REQUEST_TIMEOUT);
cancelers.push(canceler);
return canceler.promise;
}
};
}
function timeoutInterceptor(httpRequestsCanceller) {
return {
request(config) {
const timeout = httpRequestsCanceller.createTimeout();
return angular.extend({ timeout }, config);
}
};
}
module.exports = function($httpProvider, $provide) {
'ngInject';
$provide.service('httpRequestsCanceller', httpRequestsCancellerService);
$httpProvider.interceptors.push(timeoutInterceptor);
};
它现在运行得很好,但它有一个小缺点 - $timeout
拦截器中的request
将继续运行,即使请求完成或失败,它也将最终解析canceller
。
问题是 - 我应该关心这些待处理的$timeout
吗?为了释放一些资源或避免一些奇怪的副作用,是否有必要$timeout.cancel
他们?