第一次发文, 仅纪念我开源的第一个npm包esdese
始于回调
早期的时候, 用jquery的ajax都是一层套一层, 2层的时候倒还好, 一旦多了就比较麻烦了.
后来使用了promise, 虽然说好了一些, 但是有些时候还是层级比较深. 很难受
上个月的时候, 正好有个小程序的项目, 我就把授权的流程整理了一遍, 就发现这样的一个问题
var checkNet = function(){//检查网络
//...
}
var getSetting = function(){//获取权限
//...
}
//...
var getToken = function(){//获取token
//...
}
复制代码
一写下来发现方法接近10个, 我想把这些方法都整合起来, 但是好多都是前后依赖的关系, promise.all解决不了, 处理起来很麻烦, 索性就写了一个递归处理
var process = function(list){
return new Promise((resolve, reject) => {
if(list[0]){
list[0]().then(res => {
if(list.length == 1 ){
resolve();
}else{
process(list.slice(1)).then(res => resolve(), _ => reject())
}
}, _ => reject())
}
});
}
process([checkNet, getSetting,'...', getToken]).then(res => {
///...
})
复制代码
功能比较单一, 只能解决当前问题
前段时间看到一本js书(JavaScript异步编程)上提到一个库, 引起了我的兴趣
叫做step, 观察了一番源码之后, 发现它的实现方法很巧妙, 但是可惜只能在node.js上跑
以下是它的核心代码:
function step(){
var steps = Array.prototype.slice.call(arguments);
function next(){
//...
var fn = steps.shift();
//...
var result = fn.apply(next, arguments);
//...
}
//...
}
复制代码
使用起来就像这样子:
step(
function(){
setTimeout(this, 20000);
},
function(){
console.log('sucesss');
}
)
复制代码
2秒后输出success, 我个人是非常喜欢这种调用方式的.
但是当时没有自己写一个库的想法(手动狗头).
直到几天前, 看了vue的早期版本实现(尤大佬流弊), 就想自己写一个试一下, 虽然知道大致的原理, 但是光说不练假把式
动手了之后就发现这样的一个东西:
[].forEach.call(eles, el => {
[].forEach.call(el.attributes, attr => {
console.dir(attr);
//...
});
});
复制代码
我一看到这样格式就觉得很僵硬, 虽然能提出去变成方法, 但这本不是我想要的样子
灵光一闪, 我能不能把step用进来, 说做就做, 但是一用发现了问题:
step(
function(){
[1, 2, 3].forEach(this);
},
function(i){
console.log('i:', i);
}
)
复制代码
结果只输出了1
因为传进去的方法被shift掉了, 只能执行一次
还有err优先的原则导致一个参数是错误描述
this.gruop也不能满足当前需求. 于是我就想自己写一个类似的库来处理循环的流程.
esdese
一番操作之后, 还真我被搞出来了:
var esdese = function(){
var fns = [].slice.call(arguments);
var next = function(i){
i ++;
return function(){
fns[i].apply(next(i), arguments);
}
}
next(-1)();
}
复制代码
这是最开始的版本, 跟step一样精简, 但是实现思路确实不太一样, 结合一个例子看看:
esdese(
function(){
[1, 2, 3].forEach(this);
},
function(i){
console.log('i:', i);
},
function(){
console.log('success');
}
)
//console.log
//1: 1
//success
//1: 2
//success
//1: 3
//success
复制代码
当然也能满足普通的异步流程
esdese(
function(){
setTimeout(this, 20000);
},
function(){
console.log('success');
}
)
复制代码
也有其他的一些用法, 扩展了类似step的group方法, github 你可以猛戳前往观察
当前function的所有group执行完毕, 才会执行下个方法, 也就是分组并行处理, 如下:
esdese(
function(){
var group = this.group();
//1: group has name
// setTimeout(group('a'), 2000);
// setTimeout(group('b'), 2000);
for(var i = 0; i < 3; i ++){
//2: group no name
//3: group has name
setTimeout(group(/*'time'*/).param(i), 1000 * i);
}
},
function(a, b, c){
console.log(a, b, c);
//1: { a: undefined, b: undefined } undefined undefined
//2: 0 1 2
//3: { time: [ 0, 1, 2 ] } undefined undefined
}
)
复制代码
param方法就是封装了bind方法, 传递一个参数过去, this 和 group都可以调用
增加了一个内部存储对象 this.data, 前面保存的在后面可以使用
使用了esdese之后, 早期版本的vue也写出来了, 当然不是完全版的 test
why
至此文章就要结束了.
关于为什么叫esdese, 初一看确实绕口, 什么es什么的
但是了解的人就知道这是什么, 没错