前端實現http線程池

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章