美文网首页
Promise技术探究

Promise技术探究

作者: 常青_1f93 | 来源:发表于2018-01-13 23:35 被阅读0次

    1.promise简介

      1.1    

              Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做。

            Promise表示一个异步操作的最终结果。与Promise最主要的交互方法是通过将函数传入它的then方法从而获取得Promise最终的值或Promise最终最拒绝(reject)的原因。

    1.2  Promise状态

    一个Promise必须处在其中之一的状态:pending, fulfilled 或 rejected.

    如果是pending状态,则promise:

    可以转换到fulfilled或rejected状态。

    如果是fulfilled状态,则promise:

    不能转换成任何其它状态。

    必须有一个值,且这个值不能被改变。

    如果是rejected状态,则promise可以:

    不能转换成任何其它状态。

    必须有一个原因,且这个值不能被改变。

    ”值不能被改变”指的是其identity不能被改变,而不是指其成员内容不能被改变。

    1.3 then 方法

    一个Promise必须提供一个then方法来获取其值或原因。

    Promise的then方法接受两个参数:

    promise.then(onFulfilled, onRejected)

    onFulfilled 和 onRejected 都是可选参数:如果onFulfilled不是一个函数,则忽略之。如果onRejected不是一个函数,则忽略之。

    如果onFulfilled是一个函数:它必须在promise fulfilled后调用, 且promise的value为其第一个参数。

    它不能在promise fulfilled前调用。不能被多次调用。

    如果onRejected是一个函数,它必须在promise rejected后调用, 且promise的reason为其第一个参数。

    它不能在promise rejected前调用。不能被多次调用。

    onFulfilled 和 onRejected 只允许在 execution context 栈仅包含平台代码时运行. 

    onFulfilled 和 onRejected 必须被当做函数调用 (i.e. 即函数体内的 this 为undefined). 

    对于一个promise,它的then方法可以调用多次.

    当promise fulfilled后,所有onFulfilled都必须按照其注册顺序执行。

    当promise rejected后,所有OnRejected都必须按照其注册顺序执行。

    then 必须返回一个promise 

    promise2 = promise1.then(onFulfilled, onRejected);

    如果onFulfilled 或 onRejected 返回了值x, 则执行Promise 解析流程[[Resolve]](promise2, x).

    如果onFulfilled 或 onRejected抛出了异常e, 则promise2应当以e为reason被拒绝。

    如果 onFulfilled 不是一个函数且promise1已经fulfilled,则promise2必须以promise1的值fulfilled.

    如果 OnReject 不是一个函数且promise1已经rejected, 则promise2必须以相同的reason被拒绝.

    2.使用promise

    let promise = new Promise((resolve, reject) => {

            setTimeout(function(){

                    let num =Math.random();

                      if(num<.5){

                            resolve(num);

                      }else{

                            reject('失败');

                      }

            })

    });

    promise.then(Fulfilled,Rejected)

    构造一个Promise实例需要给Promise构造函数传入一个函数。

    传入的函数需要有两个形参,两个形参都是function类型的参数。

    第一个形参运行后会让Promise实例处于resolve状态,所以我们一般给第一个形参命名为resolve,使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作

    第一个形参运行后会让Promise实例处于reject状态,所以我们一般给第一个形参命名为reject,将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作

    3 .自己实现promise

    const PENDING = 'pending';//初始态

    const FULFILLED =  'fulfilled';//成功态

    const REJECTED =  'rejected';//失败态

    function Promise(executor){

      let self = this;//先缓存当前promise实例

      self.status = PENDING;//设置状态

      //定义存放成功的回调的数组

      self.onResolvedCallbacks = [];

      //定义存放失败回调的数组

      self.onRejectedCallbacks = [];

      //当调用此方法的时候,如果promise状态为pending,的话可以转成成功态,如果已经是成功态或者失败态了,则什么都不做

      function resolve(value){ 

        if(value!=null &&value.then&&typeof value.then == 'function'){

          return value.then(resolve,reject);

        }

        //如果是初始态,则转成成功态

        setTimeout(function(){

          if(self.status == PENDING){

            self.status = FULFILLED;

            self.value = value;//成功后会得到一个值,这个值不能改

            //调用所有成功的回调

            self.onResolvedCallbacks.forEach(cb=>cb(self.value));

          }

        })

      }

      function reject(reason){ 

        setTimeout(function(){

          //如果是初始态,则转成失败态

          if(self.status == PENDING){

            self.status = REJECTED;

            self.value = reason;//失败的原因给了value

            self.onRejectedCallbacks.forEach(cb=>cb(self.value));

          }

        });

      }

      try{

        //因为此函数执行可能会异常,所以需要捕获,如果出错了,需要用错误 对象reject

        executor(resolve,reject);

      }catch(e){

        //如果这函数执行失败了,则用失败的原因reject这个promise

        reject(e);

      };

    }

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

      if(promise2 === x){

        return reject(new TypeError('循环引用'));

      }

      let called = false;//promise2是否已经resolve 或reject了

      if(x instanceof Promise){

        if(x.status == PENDING){

          x.then(function(y){

            resolvePromise(promise2,y,resolve,reject);

          },reject);

        }else{

          x.then(resolve,reject);

        }

      //x是一个thenable对象或函数,只要有then方法的对象,

      }else if(x!= null &&((typeof x=='object')||(typeof x == 'function'))){

        //当我们的promise和别的promise进行交互,编写这段代码的时候尽量的考虑兼容性,允许别人瞎写

      try{

        let then = x.then;

        if(typeof then == 'function'){

          //有些promise会同时执行成功和失败的回调

          then.call(x,function(y){

            //如果promise2已经成功或失败了,则不会再处理了

              if(called)return;

              called = true;

              resolvePromise(promise2,y,resolve,reject)

          },function(err){

            if(called)return;

            called = true;

            reject(err);

          });

        }else{

          //到此的话x不是一个thenable对象,那直接把它当成值resolve promise2就可以了

          resolve(x);

        }

      }catch(e){

        if(called)return;

        called = true;

        reject(e);

      }

      }else{

        //如果X是一个普通 的值,则用x的值去resolve promise2

        resolve(x);

      }

    }

    //onFulfilled 是用来接收promise成功的值或者失败的原因

    Promise.prototype.then = function(onFulfilled,onRejected){

      //如果成功和失败的回调没有传,则表示这个then没有任何逻辑,只会把值往后抛

      onFulfilled = typeof onFulfilled == 'function'?onFulfilled:function(value){return  value};

      onRejected = typeof onRejected == 'function'?onRejected:reason=>{throw reason};

      //如果当前promise状态已经是成功态了,onFulfilled直接取值

      let self = this;

      let promise2;

      if(self.status == FULFILLED){

        return promise2 = new Promise(function(resolve,reject){

          setTimeout(function(){

            try{

              let x =onFulfilled(self.value);

              //如果获取到了返回值x,会走解析promise的过程

              resolvePromise(promise2,x,resolve,reject);

            }catch(e){

              //如果执行成功的回调过程中出错了,用错误原因把promise2 reject

              reject(e);

            }

          })

        });

      }

      if(self.status == REJECTED){

        return promise2 = new Promise(function(resolve,reject){

          setTimeout(function(){

            try{

              let x =onRejected(self.value);

              resolvePromise(promise2,x,resolve,reject);

            }catch(e){

              reject(e);

            }

          })

        });

      }

      if(self.status == PENDING){

      return promise2 = new Promise(function(resolve,reject){

        self.onResolvedCallbacks.push(function(){

            try{

              let x =onFulfilled(self.value);

              //如果获取到了返回值x,会走解析promise的过程

              resolvePromise(promise2,x,resolve,reject);

            }catch(e){

              reject(e);

            }

        });

        self.onRejectedCallbacks.push(function(){

            try{

              let x =onRejected(self.value);

              resolvePromise(promise2,x,resolve,reject);

            }catch(e){

              reject(e);

            }

        });

      });

      }

    }

    module.exports =Promise;

    4 自己实现promise.all

    function gen(times,cb){

      let result = [],count=0;

      return function(i,data){

        result[i] = data;

        if(++count==times){

          cb(result);

        }

      }

    }

    Promise.all = function(promises){

             return new Promise(function(resolve,reject){

                        let done =gen(promises.length,resolve);

                        for( let i=0;i<promises.length;i++){

                                    promises[i].then(function(data){done(i,data);},reject);

                        }

             });

    }

    5. 自己实现 Promise.race

    Promise.race =function(promises){

        return new Promise(function(resolve,reject){

                for(let i=0;i<promises.length;i++){

                    promises[i].then(resolve,reject);

                  }

        });

    }

    6. 自己实现 Promise.resolve

    Promise.resolve =function(value){

            return new Promise(function(resolve){

                    resolve(value);

              });

    }

    7. 自己实现 Promise.resolve

    Promise.reject =function(reason){

               return new Promise(function(resolve,reject){

                    reject(reason);

              });

    }

    相关文章

      网友评论

          本文标题:Promise技术探究

          本文链接:https://www.haomeiwen.com/subject/kmyhoxtx.html