目录 · 9 个章节
代码
let Sequence = function(){
let i = -1, args = arguments, l = args.length;
(function lambda(){
return new Promise((next)=>{
i ++;
if(i<l) args[i](next);
}).then(lambda);
})();
}
用法
Sequence(
n=>{
// ...
n();
},
n=>{
//...
n();
}
)
实现过程:
第1步
理解promise,仅传入resolve,以减少不必要的干扰。
let p1 = new Promise((resolve)=>{
resolve(1);
});
p1.then(console.log);
let p2 = new Promise((resolve)=>{
resolve(1);
});
p2.then( (i)=>{
console.log(100*i)
});
第2步:
理解promise对回调地狱的优化。
new Promise((resolve)=>{
let e = 1;
resolve(e);
}).then(
(e)=>{
return new Promise((resolve)=>{
console.log(e);
resolve(e+1);
});
}).then(
(e)=>{
return new Promise((resolve)=>{
console.log(e);
resolve(e+1);
});
}).then(console.log);
第3步
抽象代码,精简主流程。
function promiseCount(e){
return new Promise((resolve)=>{
console.log(e);
resolve(e+1);
});
}
new Promise((resolve)=>{
resolve(1);
}).then(
promiseCount
).then(
promiseCount
).then(console.log);
第4步
编写执行器,把setTimeout作为测试用异步事件。执行器内部设置index作 “辅助指针” 指向当前递归事件。
let eventArray = [
(callback)=>{
console.log(1);
$.ajax({
url,
success(){
callback();
}
})
},
(callback)=>{
console.log(2);
setTimeout(callback,100);
},
(callback)=>{
console.log(3);
setTimeout(callback,100);
},
(callback)=>{
console.log(4);
setTimeout(callback,100);
},
(callback)=>{
console.log(5);
setTimeout(callback,100);
}
];
function Sequence(eventArray){
let index = -1;
(function lambda(){
return new Promise((resolve)=>{
index ++; // 指向队列中的下一个事件
if(index<eventArray.length){
eventArray[index](resolve); // 把resolve交由当前事件的回调函数处理,即当前事件执行完之后就会执行then中新的lambda,得到的效果是“同步”
}
}).then(lambda);
})();
}
Sequence(eventArray);
第5步 (选看)
增加数据收集器
let eventArray = [
(callback)=>{
console.log(1);
setTimeout(function(){
callback().collector.z=0;
callback().resolve();
},100);
},
(callback)=>{
console.log(2);
setTimeout(function(){
callback().collector.a=1;
callback().resolve();
},100);
},
(callback)=>{
console.log(3);
setTimeout(function(){
callback().collector.b=2;
callback().resolve();
},100);
},
(callback)=>{
console.log(4);
setTimeout(function(){
callback().collector.c=3;
callback().resolve();
},100);
},
(callback)=>{
console.log(5);
setTimeout(function(){
callback().collector.d=4;
callback().resolve();
},100);
}
];
let Sequence = function(eventArray){
let index = -1, events = eventArray;
let collector = {};
(function lambda(){
return new Promise((resolve)=>{
index ++;
if(index<events.length){
events[index](()=>{
return {
resolve,
collector,
}
});
}
}).then(lambda);
})();
this.getData = function(){
return collector;
}
this.clear = function(){
collector = null;
}
}
let ev = new Sequence(eventArray);
setTimeout(function(){
console.log(ev.getData())
},2000);
collector会一直存在ev对象的内部,仅能通过调用getData获取。当然还可以往Sequence里添加更多方法。
第6步
提炼核心, 并把 resolve 改为 next.
let Sequence = function(eventArray){
let index = -1;
(function lambda(){
return new Promise((next)=>{
index ++;
if(index<eventArray.length){
eventArray[index](next);
}
}).then(lambda);
})();
}
new Sequence([
(next)=>{
setTimeout(()=>{
// do something
console.log(1);
next();
},100);
},
(next)=>{
setTimeout(()=>{
// do something
console.log(2);
next();
},100);
},
(next)=>{
setTimeout(()=>{
// do something
console.log(3);
next();
},100);
},
(next)=>{
setTimeout(()=>{
// do something
console.log(4);
next();
},100);
},
(next)=>{
setTimeout(()=>{
// do something
console.log(5);
next();
},100);
}
]);
最后一步
再次精简代码并提炼写法,减少调用键入次数。
let Sequence = function(){
let i = -1, args = arguments, l = args.length;
(function lambda(){
return new Promise((next)=>{
i ++;
if(i<l) args[i](next);
}).then(lambda);
})();
}
new Sequence(
next=>{
setTimeout(()=>{
// do something
console.log(1);
next();
},100);
},
next=>{
setTimeout(()=>{
// do something
console.log(2);
next();
},100);
},
next=>{
setTimeout(()=>{
// do something
console.log(3);
next();
},100);
},
next=>{
setTimeout(()=>{
// do something
console.log(4);
next();
},100);
},
next=>{
setTimeout(()=>{
// do something
console.log(5);
next();
},100);
}
);
最终结果
let Sequence = function(){
let i = -1, args = arguments, l = args.length;
(function lambda(){
return new Promise((next)=>{
i ++;
if(i<l) args[i](next);
}).then(lambda);
})();
}
发布于 NPM, 安装:npm i zfc-sequence
最终用法
let sequence = require('zfc-sequence');
sequence(
next=>{
setTimeout(()=>{
// ...
next();
},1000)
},
next=>{
setTimeout(()=>{
// ...
next();
},1000)
},
next=>{
setTimeout(()=>{
// ...
next();
},1000)
},
next=>{
setTimeout(()=>{
// ...
next();
},1000)
}
);