ES6__异步开发优化

一:JS事件循环

  1:同步调用

    同步调用是一种阻塞式调用,调用要等待双方执行完毕才返回,他是一种单向调用。

  2:回调

    回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。

  3:异步调用

    异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方,比如浏览器点击事件中,用户点击后,会调用JS中的回调函数。

  异步的实现原理:  

    

 首先左上角的Call stack(调用栈)会把代码一行一行的执行,遇到addEVentListener,也就是事件,那么它不会执行,会托管在implementation-specific(可以理解为浏览器)中,右上角的implementation-specific会把这个事件记下来,当有人点击时,那么它会load成一个消息存放在右下角的message queue中,然后Event Loop(事件循环)会一直在那里循环,查看message queue中的消息,有消息,就把它扔回调用栈,然后执行call back的事件。

 

二:ES6

  阮大大的《ECMAScript入门》  http://es6.ruanyifeng.com/

  1: promise  

    new Promise((resolve, reject) => {
        console.log('begin promise')
        setTimeout(resolve, 1000)
    }).then(() => {
        console.log('over')
    })

  这个是非常简单的代码,先new promise传入2个参数,resolve代表成功会怎么样,reject代表失败会怎么样,上面的代码的意思是先输出'begin promise'resolve成功后1秒后输出'over'。then()的意思是resolve之后立即执行。

    new Promise((resolve,reject)=>{
        console.log('begin')
        setTimeout(function() {
            resolve();
        },1000);
    }).then(()=>{
        console.log('1')
        return new Promise((resolve,reject)=>{
            setTimeout(function() {
                resolve();
            },1000);
        });
    }).then(()=>{
        console.log('2');
        return new Promise((resolve)=>{
            setTimeout(function(){
                resolve();
            }, 1000)
        })
    }).then(()=>{
        console.log('over');
    })

 代码依次执行后会出现'begin',1,2,'over'。 

 return new Promise的意思就是返回一个new promise, 放在上一个promise对象上,形成链式调用,新的promise就代表this的上下文,与上面的promise形成相同的结果。

 ,我们发现整一个过程就像一个瀑布流一样,但是它都嵌套在一起了。非常的不友好。

 

  2:thunk/curry化函数

    thunkAsync = thunkify(async)
    thunkAsync(params)(callback)

var Thunkify = function(fn){
        return function(){
            var args = Array.prototype.slice.call(arguments);
            return function(callback){
                //2000,callback
                args.push(callback);
                return fn.apply(this,args)
            }
        }
    }

    var thunkTimeout = Thunkify((time,callback)=>{
        setTimeout(callback, time)
    })

    //thunkTimeout(time)(callback)
    thunkTimeout(2000)(()=>{
        console.log('success');
    })

  thunkify的意思:先传入一个元素setTimeout(),但是它没有被立即调用,是先放在了这里,然后有返回了一个函数,返回的这个函数是把arguments里面的东西存起来,有就是2000,然后又返回一个函数,这个返回函数传入的才是最终的callback,在这个函数中有把callback push给了args,那么args的状态就是2000,callback,然后最后一个return就是进行一开始我们保存的setTimeout的调用。

  3:generator

function* helloGenerator(){
        console.log('generator');
        yield 'world'
        console.log('finish')
    }
    // //执行generator
    var generatorResult = helloGenerator();
    console.log(generatorResult.next().value);
    console.log(generatorResult.next());

  generator要记住2点,next和yield,我们可以通过next()来控制yield的执行。next是继续执行,yield是暂停。

var gen = function* (){
        //把刚才的thunk函数拿过来,放在yield的后面
        //只需要接着传一个callback就可以执行了
        var r1 = yield thunkTimeout(2000);
        console.log(r1);
        //把刚才的thunk函数拿过来,放在jield的后面
        //只需要接着传一个callback就可以执行了
        var r2 = yield thunkTimeout(2000);
        console.log(r2)
    }
    //这是一个手动执行的版本
    var g = gen();
    //这个value指向的是,刚才我们已经传入的setTimeout(2000)
    g.next().value(function(){
        //这个function就是我们的callback
        //在i这里,已经完成了第一个setTimeout的过程
        var r2 = g.next('the first function complete');
        //这里的value,指向的是第二个setTimeout(2000)
        r2.value(function(){
            //完全的执行
            g.next('the second function complete');
        })
    })  

  

  三:异步优化

    //像这样才能向上面那样2秒2秒的执行
    setTimeout(function(){
        console.log('the first function complete')
        setTimeout(function(){
            console.log('the second function complete')
        }, 2000)
    }, 2000)

我们要想实现上面的效果,有不想一直的嵌套。怎么办?

    //thunk/curry化函数
    var Thunkify = function(fn){
        //传入一个functuion:setTimeout
        //这个function fn,没有被立即调用,而是被放在了这里,先不管
        //返回了另一个函数
        return function(){
            //把arguments里面的东西存了起来,2000
            var args = Array.prototype.slice.call(arguments);
            //又返回了一个新的函数
            //这个函数传入的,才是最终的callback
            return function(callback){
                //完成push以后,args的状态是什么
                //2000,callback
                args.push(callback);
                //最终在进行一开始我们保存的setTimeout的调用
                return fn.apply(this,args)
            }
        }
    }

    var thunkTimeout = Thunkify((time,callback)=>{
        setTimeout(callback, time)
    })

        var gen = function* (){
        //把刚才的thunk函数拿过来,放在jield的后面
        //只需要接着传一个callback就可以执行了
        var r1 = yield thunkTimeout(1000);
        console.log('the first function1 complete');
        var r2 = yield thunkTimeout(2000);
        console.log('the first function2 complete');
        var r3 = yield thunkTimeout(3000);
        console.log('the first function3 complete');
        var r4 = yield thunkTimeout(4000);
        console.log('the first function4 complete');
        var r5 = yield thunkTimeout(5000);
        console.log('the first function5 complete');
    }
    

    function run(gen){
        //第一次把generator执行
        var g = gen();
        function nextRun(r){
            //在第一个行进行了一次next
            var next = g.next(r);
            if(next.done == true){
                return;
            }
            if(typeof next.value.then == 'function'){  //promise要加一个then,才执行,所以这里加一个判断
                next.value.then(nextRun)
            }else{
                //第一次value
                next.value(nextRun)
            }
        }
        nextRun();
    }
    run(gen);

  run函数就是用了递归,递归简单点来说,就是自己调用自己。  

  OK,大功告成。我好像还是第一次写这么认真的博客。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值