最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 依据规范实现Promise

    正文概述 掘金(熙宸)   2021-08-13   497

    Promise 构造以及状态声明

    1.通过new关键字使用Promise,所以应该用构造函数或者class来实现

     class HSPromise {    
         constructor() {
             
          }  
     }
    

     2.定义三种状态类型

     const PENDING = 'pending'
     const FULFILLED = 'fulfilled' 
     const REJECTED = 'rejected'
    

    3.设置初始状态

    class HSPromise {        constructor() { 
           // 初始状态为pending      
           this.status = PENDING;    
           this.value = null;         
           this.reason = null;   
        }  
      }
    

    resolve 和 reject 方法

     1. 根据规范, 这两个方法是要更改status的, 从pending改到fulfilled/rejected.

     2. 注意两个函数的入参分别是value 和 reason 

    class HSPromise {        constructor() {     
           // 初始状态为pending     
           this.status = PENDING;         
           this.value = null;           
           this.reason = null; 
        }      
        resolve(value) {          
           if (this.status === PENDING) {     
               this.status = FULFILLED;        
               this.value = value;          
           }     
        }      
        reject(reason) {    
            if (this.status === PENDING) {         
            this.status = REJECTED;          
            this.reason = reason;         
           }        
        }   
     }
    

    Promsie 入参

     1. 入参是一个函数, 函数接收resolve和reject两个参数.

     2. 注意在初始化promise的时候, 就要执行这个函数, 并且有任何报错都要通过reject抛出去

       class HSPromise {        constructor(fn) {  
              // 初始状态为pending   
              this.status = PENDING;  
              this.value = null;      
              this.reason = null;        
              try {            
                  fn(this.resolve.bind(this), this.reject.bind(this));    
              } catch (e) {     
                 this.reject(e);     
              }       
         }      
         resolve(value) {   
             if (this.status === PENDING) {           
               this.status = FULFILLED;      
               this.value = value;     
            }   
         }       
         reject(reason) {      
             if (this.status === PENDING) {    
                this.status = REJECTED;    
                this.reason = reason;      
            }    
         }   
     }
    

    then 方法的实现

    1.then接收两个参数, onFulfilled 和 onRejected

    then(onFulfilled, onRejected) {}
    

    2.检查并处理参数, 参数如果不是function,,就忽略。这个忽略指的是原样返回value或者reason

      isFunction(param) {   
         return typeof param === 'function';   
       }  
    
      then(onFulfilled, onRejected) {     
         const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled 
            : (value) => {      
                return value;      
              }      
          const rejectedFn = this.isFunction(onRejected) ? onRejected 
            : (reason) => {   
                throw reason    
              }; 
       }        
    

    3.根据当前promise的状态, 调用不同的函数

     then(onFulfilled, onRejected) {    
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled 
               : (value) => { 
                   return value;      
                 }     
        const rejectedFn = this.isFunction(onRejected) ? onRejected 
               : (reason) => { 
                   throw reason;       
                 };       
        switch (this.status) {           
               case FULFILLED: {          
                    fulFilledFn(this.value);     
                    break;
                }     
               case REJECTED: {          
                    rejectedFn(this.reason);    
                    break;
                }   
         } 
     }
    

    4. 按照这个写法, 在then函数被调用的瞬间就会执行。这时候如果status还没变成fulfilled或者rejected怎么办,很有可能还是pending的。

    首先要拿到所有的回调, 然后才能在某个时机去执行它们。新建两个数组,,分别存储成功和失败的回调;调用then的时候,如果Promise还是pending就存入数组。

    then(onFulfilled, onRejected) {    
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled 
               : (value) => { 
                   return value;       
                 }     
        const rejectedFn = this.isFunction(onRejected) ? onRejected 
               : (reason) => { 
                  throw reason;     
                 };       
        switch (this.status) {           
               case FULFILLED: {          
                    fulFilledFn(this.value);     
                    break;
                }     
               case REJECTED: {          
                    rejectedFn(this.reason);    
                    break;
                } 
               case PENDING: {       
                    this.FULFILLED_CALLBACK_LIST.push(realOnFulfilled);          
                    this.REJECTED_CALLBACK_LIST.push(realOnRejected);           
                    break;     
                }  
         } 
     } 
    

    5.在status发生变化的时候,就执行所有的回调; 这里使用es6的getter和setter, 这样更符合语义。

    当status改变时,去做一些操作。(也可以顺序执行,在给status赋值后,下面再加一行forEach,去做一些操作)

    get status(){ 
        return this._status;  
       }
    set status(newStatus) {  
        switch (newStatus) {   
              case FULFILLED: {     
                  this.FULFILLED_CALLBACK_LIST.forEach(callback => {   
                      callback(this.value);              
                  });                
                  break;             
              }             
              case REJECTED: {      
                   this.REJECTED_CALLBACK_LIST.forEach(callback => {         
                      callback(this.reason);               
                  });            
                  break;          
          }         
       }        
    }
    

    then的返回值

    1.  如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e。(需要手动catch代码,遇到报错就reject)

    then(onFulfilled, onRejected) {  
          const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled 
                 : (value) => {           
                     return value;       
                   }       
          const rejectedFn = this.isFunction(onRejected) ? onRejected 
                 : (reason) => {         
                     throw reason;     
                   };     
          const fulFilledFnWithCatch = (resolve, reject) => {       
                 try {         
                    fulFilledFn(this.value);       
                 } catch (e) {           
                    reject(e)         
                 }      
           };    
          const rejectedFnWithCatch = (resolve, reject) => {        
                 try {        
                    rejectedFn(this.reason);    
                 } catch (e) {          
                    reject(e);      
                 }     
          }     
          switch (this.status) {   
                 case FULFILLED: {       
                     return new HSPromise(fulFilledFnWithCatch);        
                 }    
                 case REJECTED: {  
                     return new HSPromise(rejectedFnWithCatch);           
                 }       
                 case PENDING: {            
                     return new HSPromise((resolve, reject) => {          
                        this.FULFILLED_CALLBACK_LIST.push(() => 
                             fulFilledFnWithCatch(resolve, reject));     
                        this.REJECTED_CALLBACK_LIST.push(() => 
                             rejectedFnWithCatch(resolve, reject));        
                      })         
                 }     
             }   
     }
    

    2. 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值。

     const fulFilledFnWithCatch = (resolve, reject) => {    
          try {        
               fulFilledFn(this.value);           
               resolve(this.value);          
           } catch (e) {    
               reject(e)    
           }      
      }
    

    3. 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因。

    需要注意的是,如果promise1的onRejected执行成功了,promise2应该被resolve

    const rejectedFnWithCatch = (resolve, reject) => {      
        try {      
           rejectedFn(this.reason);       
           if (this.isFunction(onRejected)) { 
                 resolve();          
             }    
        } catch (e) {       
            reject(e);      
        }   
    }
    

    4. 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行resolvePromise方法

    then(onFulfilled, onRejected) {  
          const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled 
                 : (value) => {           
                     return value;       
                   }       
          const rejectedFn = this.isFunction(onRejected) ? onRejected 
                 : (reason) => {         
                     throw reason;     
                   };     
          const fulFilledFnWithCatch = (resolve, reject) => {       
                 try {         
                     if (!this.isFunction(onFulfilled)) {      
                         resolve(this.value);            
                      } else {             
                         const x = fulFilledFn(this.value);   
                         this.resolvePromise(newPromise, x, resolve, reject);              
                        }     
                 } catch (e) {           
                    reject(e)         
                 }      
           };    
          const rejectedFnWithCatch = (resolve, reject) => {        
                 try {        
                    if (!this.isFunction(onRejected)) {          
                         reject(this.reason);           
                    } else {                 
                         const x = rejectedFn(this.reason);       
                         this.resolvePromise(newPromise, x, resolve, reject);            
                       }   
                 } catch (e) {          
                    reject(e);      
                 }     
          }     
          switch (this.status) {   
                 case FULFILLED: {       
                     const newPromise = new HSPromise((resolve, reject) =>                     
                       fulFilledFnWithCatch(resolve, reject, newPromise))            
                     return newPromise       
                 }    
                 case REJECTED: {  
                     const newPromise = new HSPromise((resolve, reject) =>                     
                       rejectedFnWithCatch(resolve, reject, newPromise))      
                     return newPromise             
                }       
                 case PENDING: {            
                     const newPromise = new HSPromise((resolve, reject) => {                           
                      this.FULFILLED_CALLBACK_LIST.push(() => 
                           fulFilledFnWithCatch(resolve, reject, newPromise));
                      this.REJECTED_CALLBACK_LIST.push(() => 
                          rejectedFnWithCatch(resolve, reject, newPromise));            
                      });                 
                     return newPromise;
                 }     
             }   
     } 
    

    resolvePromise 方法

    resolvePromise(newPromise, x, resolve, reject) {    
        // 如果 newPromise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise    
        // 这是为了防止死循环     
       if (newPromise === x) {        
           return reject(new TypeError('The promise and the return value are the same'));  
       } 
       if (x instanceof MPromise) {      
             // 如果 x 为 Promise ,则使 newPromise 接受 x 的状态      
             // 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y     
             // 这个if跟下面判断then然后拿到执行其实重复了,可有可无      
             x.then((y) => {           
                resolvePromise(newPromise, y, resolve, reject);        
             }, reject);     
       } else if (typeof x === 'object' || this.isFunction(x)) {      
             // 如果 x 为对象或者函数       
             // 这个坑是跑测试的时候发现的,如果x是null,应该直接resolve      
             if (x === null) {         
              return resolve(x);        
             }          
             let then = null; 
             try {      
                 // 把 x.then 赋值给 then          
                 then = x.then;        
             } catch (error) {          
                 // 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise      
                 return reject(error);        
              }          
             // 如果 then 是函数        
             if (this.isFunction(then)) {     
                 let called = false;        
                 // 将 x 作为函数的作用域 this 调用之        
                 // 传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,
                 //第二个参数叫做 rejectPromise       
                // 名字重名了,直接用匿名函数了    
                try {               
                   then.call(         
                        x,         
                        // 如果 resolvePromise 以值 y 为参数被调用,则运行 resolvePromise   
                        (y) => {             
                        // 如果 resolvePromise 和 rejectPromise 均被调用,   
                        // 或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用  
                        // 实现这条需要前面加一个变量called     
                           if (called) return;                
                           called = true;               
                           resolvePromise(promise, y, resolve, reject);         
                    },                   
                       // 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise     
                       (r) => {              
                           if (called) return;            
                           called = true;        
                           reject(r);   
                         });           
                    } catch (error) {        
                    // 如果调用 then 方法抛出了异常 e:          
                    // 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之    
                        if (called) return;          
                        // 否则以 e 为据因拒绝 promise      
                        reject(error);          
                     }         
                } else {       
                     // 如果 then 不是函数,以 x 为参数执行 promise     
                     resolve(x);         
                }        
          } else {       
             // 如果 x 不为对象或者函数,以 x 为参数执行 promise         
             resolve(x);     
        }  
     }
    

    onFulfilled 和 onRejected 是微任务

    用queueMicrotask包裹执行函数

    const fulFilledFnWithCatch = (resolve, reject) => {  
       queueMicrotask(() => {     
           try {         
                if (!this.isFunction(onFulfilled)) {      
                    resolve(this.value);            
                } else {             
                    const x = fulFilledFn(this.value);   
                    this.resolvePromise(newPromise, x, resolve, reject);              
                }     
           } catch (e) {           
                reject(e)         
           }      
       }) }    
    const rejectedFnWithCatch = (resolve, reject) => {  
       queueMicrotask(() => {     
           try {        
                if (!this.isFunction(onRejected)) {          
                    reject(this.reason);           
                } else {                 
                    const x = rejectedFn(this.reason);       
                    this.resolvePromise(newPromise, x, resolve, reject);            
                }   
           } catch (e) {          
               reject(e);      
           }    
       }) 
    }     
    

    catch方法

      catch (onRejected) {  
          return this.then(null, onRejected);   
       }
    

    Promise.resolve

    1. 将现有对象转为Promise对象,如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(又称 thenable 对象),则返回一个新的 Promise 对象,且它的状态为fulfilled。

     

    static resolve(param) {    
        if (param instanceof HSPromise) {   
             return param;  
          }
         return new MyPromise(function (resolve) {         resolve(param);   });}
    

    Promise.reject

    1. 返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。

    static reject(reason) {     
       return new MPromise((resolve, reject) => {      
          reject(reason);      
        });   
     }
    

    Promise.race

    const p = Promise.race([p1, p2, p3])

    1. 该方法是将多个 Promise 实例,包装成一个新的 Promise 实例。只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

     static race(promiseList) {    
        return new MPromise((resolve, reject) => {   
             const length = promiseList.length;    
             if (length === 0) {           
                return resolve();        
             } else {              
                 for (let i = 0; i < length; i++) {   
                     HSPromise.resolve(promiseList[i]).then(   
                         (value) => {                
                           return resolve(value);      
                         },                
                        (reason) => {                 
                           return reject(reason);     
                        });           
                  }       
             }     
       })   
     }
    

    起源地下载网 » 依据规范实现Promise

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元