不知道下面的主意对不对,若有毛病还请大佬指正
需求剖析
有一批装备,数目许多,须要为他们开启长途驱动(即挪用背景的长途驱动接口),问题是背景处置惩罚长途驱动只能一台一台装备处置惩罚,如果装备数目许多,背景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>