前端实现http线程池
背景:前端有时候需要在一个页面循环给后台发起http请求,加入前端页面的这个循环次数有很多,而后台服务的并发又有限,那么如果我们不对请求的频率做限制,就会出现很多请求超时或者失败的情况,造成很不好的业务体验。如果做过后台的人,面对这种业务场景,很容易想到线程池的概念。今天我们就在前端js中实现这么一个线程池的功能来解决这个问题。
首先要清除我们这里边需要关键的两个关键角色,一个是线程任务-task,一个是线程池-threadPool。我们分别来分析这两个对象需要有哪些要素。
先说线程任务。他需要具备以下几个特性:
1、要可以通过new的方法来创建这个对象。这个用来让我们可以通过参数的方法循环创建http请求任务。
2、task对象需要有触发任务执行的run方法。
3、task执行结束后可以通知到线程池进行下一个任务的触发。这里我们用到一个关键的知识点promise。
再说线程池。他需要具备以下几个特性:
1、要有初始大小。最好可以动态设置线程池的大小。用以控制并发的最大数。
2、要有加入新task的入口方法。用于向线程池中加入新的任务。
3、要能够动态根据线程执行情况,触发启动下一线程的控制逻辑。
经过上边的分析之后我们就可以实现一个简单的线程池了,下边的示例是结合angular的$http实现的,其实换成其他http请求方式也可以,只要记住以上几个要点即可。当然我们要向实现的跟完整一些,还可以加入线程池的pause、resume、clear等方法。
线程任务示例:
function httpTask(){
var task = {
run:function () {
var deferred = $q.defer();
$http({
method: 'POST',
url: 'myFunction.do',
}).success(function(data,status,headers,config){
deferred.resolve();
}).error(function(data,status,headers,config){
deferred.resolve();
});
return deferred.promise;
}
};
return task;
}
线程池服务示例:
app.factory('threadPool',['$q',function ($q) {
console.log("enter threadPool factory!!!");
var poolSize = 3;
var tasks = [];
var threadCount = 0;
function getNextTask() {
if(tasks.length >0){
tasks.shift().run().then(onTaskEnd).then(getNextTask);
}
}
function onTaskEnd() {
if(threadCount > 0){
threadCount --;
}
return $q.resolve('');
}
var threadPool = {
setSize : function (size) {
poolSize = size;
return;
},
getSize : function () {
return poolSize;
},
add : function (task) {
if(threadCount < poolSize){
threadCount++;
task.run().then(onTaskEnd).then(getNextTask);
}
else{
tasks.push(task);
}
},
clear : function () {
tasks.length = 0;
tasks = [];
}
};
return threadPool;
}]);
新建任务并加入线程池
threadPool.add(new httpTask());