有一批設備,數量不少,須要爲他們開啓遠程驅動(即調用後臺的遠程驅動接口),問題是後臺處理遠程驅動只能一臺一臺設備處理,若是設備數量不少,後臺php 在30s 內處理不完就會
timeout
php
最開始的辦法,將因此設備通通交給後臺,接口只請求一次,這樣作的結果是,這個請求經常超時(不可用)
由於後臺沒法一次處理這麼多數據,因此請求超時
html
第二種想法:將全部設備分組
,好比 3個一組,而後循環分組好的列表數組,在循環內部用閉包
進行訪問請求
這樣作的結果是會有不少個ajax請求在同時進行,也沒法獲得全部請求結束的時刻的鉤子jquery
第三種想法(咱們老大的想法
):模擬線程操做
,模擬同時開啓多個線程
,全部請求即設備列表放在一個線程池內
(數組),每一個線程的工做,只有當本次工做完成後,才能夠繼續去線程池內去拿新任務
(即發送新情求),這樣就能夠控制同時請求的個數(線程數)以及請求結束的時刻的鉤子。ajax
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <!-- 一個驅動結果(每一個線程的請求)實時顯示的面板 --> <div id="drivepanel"></div> </body> <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script> <script> /* * 參數列表: 驅動設備的列表數組,驅動時長 */ var drivelist = [1,2,3,4,5,6,7,8,9,10]; // 待驅動的設備列表 var drivetime = 5; // 驅動時長 var dom = $("#drivepanel"); // 得到底層函數 return 出的對象 var runui = rundeviceui(); //向底層函數傳入須要顯示的面板 runui.init(dom); //啓動函數 runui.start(drivelist,drivetime,function(){ //程序運行中 console.log('程序運行中!'); },function(){ //程序運行結束 console.log("程序運行結束!"); }) //驅動設備的底層函數 function rundeviceui() { return { init:function(context){ this.context = context; this.r_init(); this.c_init(); }, list:[], // 列表數組,線程池(列表中的每一項至關於一個任務) drivetime:0, //驅動時長 onrun:null, //運行時函數 onend:null, //運行結束時函數 runnumber:3, //同時開啓的線程數量 c_init:function(){ //初始化一些操做 }, r_init:function(){ //綁定事件操做 }, start:function(list,drivetime,onrun,onend){ //啓動函數 var me = this; this.list = list; this.drivetime = drivetime; this.onrun = onrun; this.onend = onend; //開啓面板顯示 this.context.show(); this.run(me.runnumber,function(){ me.onend(); }) }, run:function(number,onend){ //運行時函數 var me = this; var runnow = 0; //正在運行的線程數 for(var i=0; i<number; i++){ runnow++; setTimeout(_run); //依次開啓事先設定好的線程(runnumber) } function _run(){ var data = me.list.shift(); //從線程池取出的任務 if(!data){ //假如線程池內沒任務了,調用結束函數 _runend() }else{ console.log('run',data); var selfFun = arguments.callee; //當前函數 me.showStatus(data,'已提交處理!'); // 程序運行中的鉤子 me.onrun && me.onrun(); //調用請求接口 me.ajaxFn(data,drivetime,function(){ var status = "處理成功!"; me.showStatus(data,status); setTimeout(selfFun); //再次調用自身 }) } } // 結束函數 // 當線程池內的任務處理完畢後,執行,_runend 函數,而後線程線程遞減,當正在運行的線程數爲 0 時調用任務完成函數 function _runend(){ runnow--; if(runnow <= 0){ onend && onend(); } } }, showStatus:function(devicecode,status){ //面板顯示請求的實時狀態 var me = this; //建立列表dom 元素,用 devicecode 當作 name 值 var dom = this.context.find("[name="+ devicecode +"]"); if(dom.length <= 0){ //假如該 dom 元素不存在,則建立 dom = this.c_getrow(devicecode,status); } //若是該 dom 元素已存在,則爲其附上 合適的 status 值 dom.html(devicecode + ":" + status); }, c_getrow:function(devicecode,status){ //建立dom元素 var me = this; var dom = $("<div></div>").attr('name',devicecode); this.context.append(dom); return dom; }, //模擬後臺的請求接口 ajaxFn:function(data,time,fn,fnerr){ // 噠噠噠,,,發送ajax請求,請求失敗暫不考慮 setTimeout(function(){ fn && fn(); },3000); } } } </script> </html>