js回调流程控制, 更高级, 更优雅

第一次发文, 仅纪念我开源的第一个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什么的
但是了解的人就知道这是什么, 没错

艾斯德斯 高贵.优雅又强大

end

转载于:https://juejin.im/post/5cb140ddf265da03981fb6dd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值