有一批设备,数量不少,须要为他们开启远程驱动(即调用后台的远程驱动接口),问题是后台处理远程驱动只能一台一台设备处理,若是设备数量不少,后台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>