-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
异步流程控制器实现
//最终效果:
pjs.when(["A","B"],(val)=>{
console.log(val);
});
pjs.when(["A","C"],(val)=>{
console.log(val);
});
setTimeout(()=>{
pjs.trigger("A", "dataA");
},1000)
setTimeout(()=>{
pjs.trigger("B", "dataB");
},2000)
setTimeout(()=>{
pjs.trigger("C", "dataC");
},3000)
step1 简版实现
思路:调用when的时候将异步任务(A B)用数组存起来,并将异步回调用callback存储;然后当A/B异步任务完成时调用trigger方法把异步任务数组里面的A/B删除,并且检测异步任务队列是否为空,为空时调用callback。
// 最简版
var pjs = {};
var _tasks = []; var _callback;
pjs.when = function(tasks, callback){
_tasks = tasks;
_callback = callback;
};
pjs.trigger = function(task){
_tasks.splice(task.indexOf(_tasks), 1);
if(_tasks.length == 0){
_callback();
}
};
step2 trigger时支持传值
思路:在step1的基础上 每次trigger的时候将trigger的值存入一个map里面,最后执行回调的时候把这个map作为参数传入
// 支持传值
var pjs = {};
var _tasks = []; var _callback;var valMap = {};
pjs.when = function(tasks, callback){
_tasks = tasks;
_callback = callback;
};
pjs.trigger = function(task, val){
_tasks.splice(task.indexOf(_tasks), 1);
valMap[task] = val;
if(_tasks.length == 0){
_callback(valMap);
}
};
step3 支持多个异步队列(多个when)
思路:每次调用when的时候用一个异步队列map存储多个when,每次trigger的时候在多个异步队列里面循环,删除每个异步队列的异步任务。相当于增加一个维度。
// 支持多个when
var pjs = {};
var uid = 0;
pjs.when = function(tasks, callback){
tasksMap[++uid] = {
tasks: tasks,
valMap: {},
callback: callback
};
};
pjs.trigger = function(task, val){
for(var k in tasksMap){
var uidtask = tasksMap[k].tasks;
if(uidtask.indexOf(task)==-1) continue;
var uidvalmap = tasksMap[k].valMap;
var uidcallback = tasksMap[k].callback;
uidvalmap[task] = val;
uidtask.splice(uidtask.indexOf(task), 1);
if(uidtask.length==0){
uidcallback(uidvalmap);
}
}
}
step4 优化
思路:step3里面存在一个问题,就是每次trigger都会去循环所有的异步队列,即使该异步队列里面没有trigger的任务,所以在这里需要做一个改进,在when的时候我们以异步任务为key存储它关联的异步队列(uid),在trigger的时候只需要去循环它关联的异步队列uid,优化循环
var pjs = {};
var tasksMap = {};var evtMap = {};
var uid = 0;
pjs.when = function(tasks, callback){
tasksMap[++uid] = {
tasks: tasks,
valMap: {},
callback: callback
};
tasks.map(function(evt, index){
var evtuid = evtMap[evt];
evtuid?evtuid.push(uid):evtuid = [uid];
});
};
pjs.trigger = function(task, val){
for(var i=0;i<evtMap[task].length;i++){
var uid = evtMap[task][i]
var uidtask = tasksMap[uid].tasks;
if(uidtask.indexOf(task)==-1) continue;
var uidvalmap = tasksMap[uid].valMap;
var uidcallback = tasksMap[uid].callback;
uidvalmap[task] = val;
uidtask.splice(uidtask.indexOf(task), 1);
if(uidtask.length==0){
uidcallback(uidvalmap);
}
}
}
Metadata
Metadata
Assignees
Labels
No labels