前端實現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());