你不知道的Promise

最近在掘金上刷面试题的时候不可或非的屡次遇到了Promise的问题,因而经过万能的搜索引擎,研究一番以后终于对Promise的源码才有了一个初步的理解,但愿小伙伴能在此获得一点收获javascript

你真的懂 promise 的运行机制吗?

new 一个promise的时候须要传递一个执行器函数,当即执行
执行器函数只接受两个参数 resolve reject
Promise有三个状态 pedding fulfilled rejectedjava

状态改变只能由pendding -> fulfilled 或者 pendding -> rejected
状态一经肯定就没法改变面试

咱们所了解的 then 链式调用

Promise 的 then 能够链式调用(返回一个promise对象)
可接收两个参数(可缺省),一个是成功的回调onFulfilled 一个是失败的回调onRejected数组

若是成功且有返回值,则若是返回值为Promise对象则等待promise执行完成
若是成功则走下一个Promise成功的回调不然就走失败的回调promise

若是返回值是其余类型则直接做为下一个then对应的成功或失败的回调(在成功的回调返回就走下一个then成功的回调,反之亦然)异步

源码解读

const PENDDING='pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
function Promise(fn){
   let self = this;
   /**初始化状态*/
   self.status=PENDDING;
   
   /**保存成功回调函数*/
   self.onFulfilledCallBack=[];
   /**保存失败的回到数组*/
   self.onRejectedCallBack=[];
   
   /**执行成功回调 */
   function resolve(value){
    if(self.status===PENDDING){
      self.status=FULFILLED;
      self.value=value;
      self.onFulfilledCallBack.forEach(fn=>fn(self.value))
    }
   }
   /**失败回调*/
   function reject(reason){
     if(self.status===PENDDING){
       self.status=REJECTED;
       self.reason=reason;
       self.onRejectedCallBack.forEach(fn=>fn(self.reason))
     }
   }

   /**当即执行传入的函数,并加一层捕获异常 */
   try {
     fn(resolve,reject)
   } catch (error) {
     reject(error)
   }
}


Promise.prototype.then=function(onFulfilled,onRejected){
/**确保用户在没有传入回调函数的时候将值日后传*/
  onFulfilled = typeof onFulfilled=== "function"?onFulfilled:value=>value;
  onRejected = typeof onRejected=== "function"?onRejected:reason=>{throw reason};
  let self=this;
  let promise2=new Promise(function(resolve,reject){
    if(self.status===FULFILLED){
      try {
      
        /**由于Promise是属于微任务,因此在这里须要在外层包裹一个setTimeout 保证它处于异步队列(关于这个问题的具体缘由能够百度一下js事件循环机制) */
        setTimeout(()=>{
          let x = onFulfilled(self.value);
          resolvePromise(promise2,x,resolve,reject)
        })
      } catch (error) {
        reject(error)
      }
    }else if(self.status===REJECTED){

      try {
        setTimeout(()=>{
          let x = onRejected(self.reason);
          resolvePromise(promise2,x,resolve,reject)
        })
      } catch (error) {
        reject(error)
      }
    }else if(self.status===PENDDING){
    
    /** 若是在调用then函数的时候promise状态还处于pendding状态 则将处理函数分别存入对应的成功或失败的处理函数数组中 */
    
      self.onFulfilledCallBack.push(()=>setTimeout(()=>{
        try {
          let x = onFulfilled(self.value);
          resolvePromise(promise2,x,resolve,reject)
        } catch (error) {
          reject(error)
        }
      }))

      self.onRejectedCallBack.push(()=>setTimeout(()=>{
        try {
          let x = onRejected(self.reason);
          resolvePromise(promise2,x,resolve,reject)
        } catch (error) {
          reject(error)
        }
      }))
    }
  })
  return promise2;
}

/**处理在then函数中返回值*/
function resolvePromise(promise2,x,resolve,reject){
/**确保只执行一次*/
  let used;
  
  /**若是出现传入的x==promise2 则会出现死循环,为了为了不这种状况应该在这里加一层判断 */
  if(x==promise2){
    reject(new TypeError('Chaining cycle'));
  }else if(x &&typeof x==='function'||typeof x==='object'){
    try {
      let then = x.then;
      
      /**在这里加上一层判断是为了不用户传入像{then:""}的对象*/
      if(typeof then==='function'){
        then.call(x,(y)=>{
          if(used)return;
          used=true;
          resolvePromise(promise2, y, resolve, reject);
        },e=>{
          if(used)return;
          used=true;
          reject(e)
        })
      }else{
        if(used)return;
        used=true;
        resolve(x)
      }
    } catch (error) {
      reject(error)
    }
  }else{
    x&&resolve(x)
  }
}
module.exports=Promise
复制代码

能够参考这位大佬的文章
小邵教你玩转promise函数

相关文章
相关标签/搜索