完成浅易 ES6 Promise 功用 (二)

上一篇文章【完成浅易 ES6 Promise 功用 (一)】完成了基础的异步功用。本日我们接着上次的内容继承扯,怎样完成【数据通报】以及当【回调函数返回一个新的promise】

上篇已完成的代码

function Promise(func){
    this.state = 'pending';
    this.doneList = []; 
    func(this.resolve.bind(this)); 
}

Promise.prototype = {
    
    resolve: function(){
        while(true){
            if( this.doneList.length === 0 ){
                this.state = 'done';
                break;
            }
            this.doneList.shift().apply(this);
        }
    },
    
    then: function(callback){ 
        this.doneList.push(callback); 
        if( this.state === 'done'){
            this.state = 'pending';
            this.resolve();
        }
        return this; 
    }
}

测试代码

new Promise(function(resolve){
    resolve(1)
}).then(function(data){
    console.log(data); // 1
    return 2;
}).then(function(data){
    console.log(data); // 2
});

上面的效果,就是我们要完成的。resolve的参数(只通报第一个参数,假若有)通报给第一个then内里函数作为参数,第一个then内里的函数返回值通报给第二个then内里的函数作为参数,以此类推。

症结代码

resolve: function(){
    // arguments[0]是resolve的第一个参数
    while(true){
        if( this.doneList.length === 0 ){
            this.state = 'done';
            break;
        }
        // 这里是运转then内里回调函数的处所
        this.doneList.shift().apply(this);
    }
}

怎样修正呢?除了第一次通报参数,是把resolve的参数往下通报,其他的都是把上次的效果作为下次最先(参数)。
因而,我们能够先把上次doneList内里的函数运转效果保留起来。然后,比及下次须要的时刻,再传给下一个回调函数。
代码修正:

resolve: function(){
    // arguments[0]是resolve的第一个参数
    var arg = arguments[0];
    while(true){
        if( this.doneList.length === 0 ){
            this.state = 'done';
            break;
        }
        // 这里是运转then内里回调函数的处所
        // 以数组情势传给下一个函数,然后保留新的值
        // 推断通报的参数是不是为undefined,是的话,就不必传了
        if( typeof arg === 'undefined' ){
            arg = this.doneList.shift().apply(this);
        }else{
            arg = this.doneList.shift().apply(this, [arg]);
        }   
    }
    // 保留末了的arg,保证后续的回调能继承获得参数
    this.arg = arg;
}
// 还须要修正then要领
then: function(callback){ 
    this.doneList.push(callback); 
    if( this.state === 'done'){
        this.state = 'pending';
        this.resolve(this.arg); // 注重这里也要通报参数
    }
    return this; 
}

第一次修正完美的代码,及测试效果

function Promise(func){
    this.state = 'pending';
    this.doneList = []; 
    func(this.resolve.bind(this)); 
}

Promise.prototype = {
    resolve: function(){
        // arguments[0]是resolve的第一个参数
        var arg = arguments[0];
        while(true){
            if( this.doneList.length === 0 ){
                this.state = 'done';
                break;
            }
            // 这里是运转then内里回调函数的处所
            // 以数组情势传给下一个函数,然后保留新的值
            // 推断通报的参数是不是为undefined,是的话,就不必传了
            if( typeof arg === 'undefined' ){
                arg = this.doneList.shift().apply(this);
            }else{
                arg = this.doneList.shift().apply(this, [arg]);
            }   
        }
        // 保留末了的arg,保证后续的回调能继承获得参数
        this.arg = arg;
    },
    then: function(callback){ 
        this.doneList.push(callback); 
        if( this.state === 'done'){
            this.state = 'pending';
            this.resolve(this.arg); // 注重这里也要通报参数
        }
        return this; 
    }
}

// 测试
new Promise(function(resolve){
    resolve(1)
}).then(function(data){
    console.log(data); // 1
    return 2;
}).then(function(data){
    console.log(data); // 2
});

效果截图:
《完成浅易 ES6 Promise 功用 (二)》

本日的第一个功用已完了,那末如今最先开辟第二个功用。

先看一个测试

new Promise(function(resolve){
    resolve(1)
}).then(function(data){
    console.log(data, 2); // 1,2
    return new Promise(function(resolve){
        window.setTimeout(function(){
            resolve(3);
        }, 1000);
    }).then(function(data){
        console.log(data, 4); // 3,4
        return 5;
    });
}).then(function(data){
    console.log(data, 6); // 5, 6
});

测试效果
《完成浅易 ES6 Promise 功用 (二)》

我在上面测试例子中,then回调函数中返回的promise中有意使用了耽误函数。然则,输出效果中5往后传了,而且[5,6]是在[3,4]以后,且都有一秒中的耽误。

《完成浅易 ES6 Promise 功用 (二)》
假如没有回调返回一个promise,顺序会一向根据第一行走下去,就算回调中有其他promise(只要不return),也是两条并行的线。一旦返回promise,新的promise会在这个点插进去,而且本来还没有实行的回调,也会排到新的回调列表背面了。

先来修正resolve要领,由于回调函数都是在这里运转的。

resolve: function(){
    // arguments[0]是resolve的第一个参数
    var arg = arguments[0];
    while(true){
        if( this.doneList.length === 0 ){
            this.state = 'done';
            break;
        }
        /*************************/
        if( arg instanceof Promise ){
            // 把新的promise保留起来,待会要用
            this.promise = arg;
            // 本promise没有实行完的回调悉数加入到新的回调列表
            arg.doneList = arg.doneList.concat(this.doneList);
            // 改变回调及状况
            this.doneList.length = 0;
            this.state = 'done';
            // 跳出轮回
            break;
        }
        /*************************/
        // 这里是运转then内里回调函数的处所
        // 以数组情势传给下一个函数,然后保留新的值
        // 推断通报的参数是不是为undefined,是的话,就不必传了
        if( typeof arg === 'undefined' ){
            arg = this.doneList.shift().apply(this);
        }else{
            arg = this.doneList.shift().apply(this, [arg]);
        }   
    }
    // 保留末了的arg,保证后续的回调能继承获得参数
    this.arg = arg;
}

then: function(callback){ 
    this.doneList.push(callback); 
    if( this.state === 'done'){
        this.state = 'pending';
        this.resolve(this.arg); // 注重这里也要通报参数
    }
    // 这里不能在返回this了,而是一个promise对象
    return this.promise; 
}

// 假如then没有返回promise,那末this.promise = this;

function Promise(func){
    this.state = 'pending';
    this.doneList = []; 
    func(this.resolve.bind(this));
    // 默许指向自身
    this.promise = this; 
}

本期完全代码

function Promise(func){
    this.state = 'pending';
    this.doneList = []; 
    func(this.resolve.bind(this));
    this.promise = this; 
}

Promise.prototype = {
    resolve: function(){
        // arguments[0]是resolve的第一个参数
        var arg = arguments[0];
        while(true){
            if( this.doneList.length === 0 ){
                this.state = 'done';
                break;
            }
            if( arg instanceof Promise ){
                this.promise = arg;
                arg.doneList = arg.doneList.concat(this.doneList);
                this.doneList.length = 0;
                this.state = 'done';
                break;
            }
            // 这里是运转then内里回调函数的处所
            // 以数组情势传给下一个函数,然后保留新的值
            // 推断通报的参数是不是为undefined,是的话,就不必传了
            if( typeof arg === 'undefined' ){
                arg = this.doneList.shift().apply(this);
            }else{
                arg = this.doneList.shift().apply(this, [arg]);
            }   
        }
        // 保留末了的arg,保证后续的回调能继承获得参数
        this.arg = arg;
    },
    then: function(callback){ 
        this.doneList.push(callback); 
        if( this.state === 'done'){
            this.state = 'pending';
            this.resolve(this.arg); // 注重这里也要通报参数
        }
        return this.promise; 
    }
}

完毕。感谢人人浏览,若有毛病或建议请给我留言或许发私信。

    原文作者:长颈鹿
    原文地址: https://segmentfault.com/a/1190000004358563
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞