完成浅易 ES6 Promise 功用 (一)

Promise 对象用于耽误(deferred) 盘算和异步(asynchronous ) 盘算。一个Promise对象代表着一个还未完成,但预期将来会完成的操纵。

先来一个例子 A 熟习下语法

    var p = new Promise(function(resolve, reject){
        console.log('1');
        // 运转后续的 callback 列表,比方:then,when等。不然,不会实行then内里的函数
        resolve('go next'); 
    });
    
    // 只斟酌胜利
    p.then(function(){
        console.log(2, arguments);
        return 'next';
    }, null).then(function(){
        console.log(3, arguments)
    }, null);
    
    // 输出
    1
    2 ['go next']
    3 ['next']

最初的想象

    function Promise(func){ // 吸收一个函数作为参数
    
    }
    
    Promise.prototype = {
    
        then: function(callback){ // 吸收函数作为参数
            
            return this; // 支撑链式挪用
        }
    } 

视察例 A,resolve是一个函数,而且不是用户传的,一切Promise本身应该有一个resolve要领,而且这个要领要通报给Promise组织器内里的函数作为参数。

    function Promise(func){ // 吸收一个函数作为参数
        **func(this.resolve);**
    }
    
    Promise.prototype = {
        
        **resolve: function(){
        
        }**,
        
        then: function(callback){ // 吸收函数作为参数
            
            return this; // 支撑链式挪用
        }
    }

Promise是根据递次来实行callback的,而且由resolve触发。

    function Promise(func){ // 吸收一个函数作为参数
        **this.doneList = []; // callback 列表**
        **func(this.resolve.bind(this)); // 顺带绑定this对象**
    }
    
    Promise.prototype = {
        
        resolve: function(){
            **//实行回调列表
            while(true){
                if( this.doneList.length === 0 ){
                    break;
                }
                this.doneList.shift().apply(this);
            }**
        },
        
        then: function(callback){ // 吸收函数作为参数
            **this.doneList.push(callback); // 加入到回调行列**
            return this; // 支撑链式挪用
        }
    }

好,如今写一个测试用例

    var p =new Promise(function(resolve){
            console.log('a');
            resolve();
        }).then(function(){
            console.log('b');
        });
        
     // 输出
     'a'

什么鬼?打印下p

    console.log(p);

《完成浅易 ES6 Promise 功用 (一)》

我们发明本来doneList内里另有一个函数没有运转,再运转下这个函数

    p.doneList[0].call(this);
    
    //效果
    console.log('b'); // 打印 b

打断点跟踪,发明Promise先实行resolve要领,然后实行then,把函数push到doneList。然则,再也没有实行过doneList内里的函数了。怎么办呢?我们能够给Promise加一个属性(state)来形貌当前状况,分为【未完成】(pending)和【完成】(done)。假如实行then时,状况已经是完成态,那末切换到未完成态,并实行resolve要领。

    function Promise(func){ // 吸收一个函数作为参数
        **this.state = 'pending'; // 初始化状况**
        this.doneList = []; // callback 列表
        func(this.resolve.bind(this)); // 顺带绑定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 = 'pneding';
                this.resolve();
            }
            
            return this; // 支撑链式挪用
        }
    }

用和上面相似的例子再次测试

    var p =new Promise(function(resolve){
            console.log('a');
            resolve();
        }).then(function(){
            console.log('b');
        }).then(function(){
            console.log('c');
        });

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

这下,我们自定义的Promise基本功用完成了最中心的部分了。或许有人会疑问,你这写的什么鬼?下面的代码更简朴,也能完成雷同的功用

    function Promise(func){ // 吸收一个函数作为参数
   
        func(this.resolve.bind(this)); // 顺带绑定this对象
    }
    
    Promise.prototype = {
        
        resolve: function(){
            //什么也不干    
        },
        
        then: function(callback){ // 也是吸收函数
            callback.call(this); // 直接运转
            return this; // 支撑链式挪用
        }
    }

测试用例

    var p =new Promise(function(resolve){
            console.log('d');
            resolve();
        }).then(function(){
            console.log('e');
        }).then(function(){
            console.log('f');
        });

效果:
《完成浅易 ES6 Promise 功用 (一)》

然则,文章最前面说过

Promise 对象用于耽误(deferred) 盘算和异步(asynchronous ) 盘算

而且会递次实行回调列表(doneList)。终究代码及测试

   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; 
        }
    }

    var p = new Promise(function(resolve){
            window.setTimeout(function(){
                console.log('d');
                resolve();
            }, 1000);
        }).then(function(){
            console.log('e');
        }).then(function(){
            console.log('f');
        });

    console.log('被壅塞了吗?');

输出:
《完成浅易 ES6 Promise 功用 (一)》

先输出’被壅塞了吗?’,一秒钟后接踵输出 d、e、f 。能够看出,不只没有壅塞背面的代码实行,而且回调也是根据递次实行的。

完毕。

下篇继承完美,比方数据通报以及then中函数返回一个Promise时,怎样处置惩罚。迎接人人有疑问或许发起,一起来交换。

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