不知道下面的想法对不对,如有错误还请大佬斧正
需求分析
有一批设备,数量很多,需要为他们开启远程驱动(即调用后台的远程驱动接口),问题是后台处理远程驱动只能一台一台设备处理,如果设备数量很多,后台php 在30s 内处理不完就会
timeout
最开始的办法,将所以设备统统交给后台,接口只请求一次,这样做的结果是,这个请求常常超时(不可用)
因为后台无法一次处理这么多数据,所以请求超时
第二种想法:将所有
设备分组
,比如 3个一组,然后循环分组好的列表数组,在循环内部用闭包
进行访问请求
这样做的结果是会有很多个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>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。