我有一个非常古怪的api,一次只能处理一个请求.因此,我需要确保每次发出请求时,它都会进入队列,并且该队列一次执行一个请求,直到它为空.
通常,我只使用jQuery的内置队列,因为该站点已经在使用jQuery.但是,我不确定我是否能够以某种方式装饰$ http服务,或者将其包装在另一个一次返回一个promise的服务中,或者别的什么.
Val*_*nov 40
以下是我的解决方案:http://plnkr.co/edit/Tmjw0MCfSbBSgWRhFvcg
这个想法是:每次运行服务都会向队列添加请求并返回promise.当对$ http的请求完成时,解析/拒绝返回promise并从队列中执行下一个任务(如果有的话).
app.factory('srv', function($q,$http) {
var queue=[];
var execNext = function() {
var task = queue[0];
$http(task.c).then(function(data) {
queue.shift();
task.d.resolve(data);
if (queue.length>0) execNext();
}, function(err) {
queue.shift();
task.d.reject(err);
if (queue.length>0) execNext();
})
;
};
return function(config) {
var d = $q.defer();
queue.push({c:config,d:d});
if (queue.length===1) execNext();
return d.promise;
};
});
Run Code Online (Sandbox Code Playgroud)
看起来很简单:)
基于Valentyn上面的伟大工作,我将此代码转换为独立的Angular(v1.2 +)请求/响应拦截器.它会$http自动对请求进行排队,而无需重新编写代码以便srv()在任何地方使用:
( function() {
'use strict';
angular.module( 'app' ).config( [ '$httpProvider', function( $httpProvider ) {
/**
* Interceptor to queue HTTP requests.
*/
$httpProvider.interceptors.push( [ '$q', function( $q ) {
var _queue = [];
/**
* Shifts and executes the top function on the queue (if any). Note this function executes asynchronously (with a timeout of 1). This
* gives 'response' and 'responseError' chance to return their values and have them processed by their calling 'success' or 'error'
* methods. This is important if 'success' involves updating some timestamp on some object which the next message in the queue relies
* upon.
*/
function _shiftAndExecuteTop() {
setTimeout( function() {
_queue.shift();
if ( _queue.length > 0 ) {
_queue[0]();
}
}, 1 );
}
return {
/**
* Blocks each request on the queue. If the first request, processes immediately.
*/
request: function( config ) {
var deferred = $q.defer();
_queue.push( function() {
deferred.resolve( config );
} );
if ( _queue.length === 1 ) {
_queue[0]();
}
return deferred.promise;
},
/**
* After each response completes, unblocks the next request.
*/
response: function( response ) {
_shiftAndExecuteTop();
return response;
},
/**
* After each response errors, unblocks the next request.
*/
responseError: function( responseError ) {
_shiftAndExecuteTop();
return $q.reject( responseError );
},
};
} ] );
} ] );
} )();
Run Code Online (Sandbox Code Playgroud)
理查德:你的代码很完美,但它也适用于内部请求,如template或$templateProviders.
这是仅适用于外部http请求的解决方案
/**
* Interceptor to queue HTTP requests.
*/
$httpProvider.interceptors.push(['$q', function ($q) {
var _queue = [];
/**
* Executes the top function on the queue (if any).
*/
function _executeTop() {
if (_queue.length === 0) {
return;
}
_queue[0]();
}
return {
/**
* Blocks each request on the queue. If the first request, processes immediately.
*/
request: function (config) {
if (config.url.substring(0, 4) == 'http') {
var deferred = $q.defer();
_queue.push(function () {
deferred.resolve(config);
});
if (_queue.length === 1) {
_executeTop();
}
return deferred.promise;
} else {
return config;
}
},
/**
* After each response completes, unblocks the next request.
*/
response: function (response) {
if (response.config.url.substring(0, 4) == 'http') {
_queue.shift();
_executeTop();
}
return response;
},
/**
* After each response errors, unblocks the next request.
*/
responseError: function (responseError) {
if (responseError.config.url.substring(0, 4) == 'http') {
_queue.shift();
_executeTop();
}
return $q.reject(responseError);
},
};
}]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21064 次 |
| 最近记录: |