符合a+规范品味promise

148 阅读3分钟

在JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现,但是这样的做法往往让代码,与思维进入了回调地狱当中;


    function after(times,callback){
        return function(obj){
            if(--times===0){
                callback(obj)
            }
        }
    }

在相当复杂的代码中如何回避回调地狱这种情况的,Promise模式也许是一个不错,可以使异步代码看起来如同步般清新易读,从而从回调地狱中解脱出来,ES6中 已原生支持 Promise,自然而然promise也有了他的一套规范;


rules

rules

  • 1.new Promise时需要传递一个executor执行器,执行器会立刻执行
  • 2.执行器中传递了两个参数 resolve成功的函数 他调用时可以传一个值 值可以是任何值 reject失败的函数 他调用时可以传一个值 值可以是任何值
  • 3.只能从pending态转到成功或者失败
  • 4.promise实例。每个实例都有一个then方法,这个方法传递两个参数,一个是成功另一个是失败
  • 5.如果调用then时 发现已经成功了 会让成功函数执行并且把成功的内容当作参数传递到函数中
  • 6.promise 中可以同一个实例then多次,如果状态是pengding 需要将函数存放起来 等待状态确定后 在依次将对应的函数执行 (发布订阅)

一个Promise存在三种状态

  • pending: 初始状态
  • resolve: 可以理解为成功
  • reject: 可以理解为失败

Analysis Promise


首先我们来看原生如何调用Promise

new Promise((resolve,reject)=>{});

这里我们可以看出再调用构造函数时,其实传递了一个执行器

如果我们自己该怎样去实现这个流程.

rule.1

    function Promise(executor){
        <!--这里的构造器传递了两个匿名函数-->
        function resolve(){
            
        }
        function reject(){
            
        }
        executor(resolve,reject)
    }

我们再看看rule.2不论是失败还是成功的情况,都会传递一个值,再结合rule3,我们可以预先给定一个预状态

   function Promise(executor){
       let _this=this;
       _this.status='pending';
       _this.value='undefined';
       _this.reason='undefined';
        function resolve(value){
            if( _this.status==='pending'){
                _this.status='resolved';
                _this.value=value;
            }
        }
        function reject(reason){
            if(_this.status==='pending'){
                _this.status='rejected';
                _this.value=value;
            }
        }
        executor(resolve,reject)
   } 

接下来我们看看rule4,每一个promise实例,都应该有一个then方法并且可以传递两个参数,一个成功,一个失败,并且返回一个promise实例

    function Promise(executor){...};
    Promise.prototype.then=function(onfulfilled,onrejected){
        //这里应该还应该处理为传递参数的情况
        onfilfulled=typeof onfilfulled==='function?onfilfulled:val=>val;
        onrejected=typeof onrejected==='function?onrejected:val=>{throw val};
        let promise2=new Promise((resolve,reject)=>{
            .......
        })
        return promise2
    }

我们做个假设如果resolve是异步的,情况又该如何处理;我觉得应该先把存储起来,然后异步调用

 function Promise(executor){
     ....
     let _this=this;
     _this.onResolves=[];
     _this.onRejects=[];
     ...
     _this.onRejects.forEach(fn=>fn())
     ...
     ...
     _this.onResolves.forEach(fn=>fn())
     ....
   } 

如果我们的resolve是一个promise那么我们就还应该进一步解析,所以应该定义一个方法来处理这种情况

function resolvePromise(promise2, x, resolve, reject) {
    ......
}

extends

Promise.all([]);

promise.resolve(cb);

Promise.reject();

Promise.race([]);

Promise.catch();//resolve=>null