作者声明

本人将迁移至个人公众号「前端Q」及「掘金」平台写文章。博客园的文章将不再及时更新发布。欢迎大家关注公众号「前端Q」及我的掘金主页https://juejin.im/user/5874526761ff4b006d4fd9a4/posts

 

Promise 必须为以下三种状态之一:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)。

基本过程:

  1. 初始化 Promise 状态(pending)
  2. 执行 then(..) 注册回调处理数组(then 方法可被同一个 promise 调用多次)
  3. 立即执行 Promise 中传入的 fn 函数,将Promise 内部 resolve、reject 函数作为参数传递给 fn ,按事件机制时机处理
  4. Promise里的关键是要保证,then方法传入的参数 onFulfilled 和 onRejected,必须在then方法被调用的那一轮事件循环之后的新执行栈中执行。

真正的链式Promise是指在当前promise达到fulfilled状态后,即开始进行下一个promise.

链式调用

先从 Promise 执行结果看一下,有如下一段代码:

复制代码
    new Promise((resolve, reject) => {         setTimeout(() => {             resolve({ test: 1 })             resolve({ test: 2 })             reject({ test: 2 })         }, 1000)     }).then((data) => {         console.log('result1', data)     },(data1)=>{         console.log('result2',data1)     }).then((data) => {         console.log('result3', data)     })     //result1 { test: 1 }    //result3 undefined
复制代码

显然这里输出了不同的 data。由此可以看出几点:

  1. 可进行链式调用,且每次 then 返回了新的 Promise(2次打印结果不一致,如果是同一个实例,打印结果应该一致。
  2. 只输出第一次 resolve 的内容,reject 的内容没有输出,即 Promise 是有状态且状态只可以由pending -> fulfilled或 pending-> rejected,是不可逆的。
  3. then 中返回了新的 Promise,但是then中注册的回调仍然是属于上一个 Promise 的。

基于以上几点,我们先写个基于 PromiseA+ 规范的只含 resolve 方法的 Promise 模型:

复制代码
function Promise(fn){          let state = 'pending';         let value = null;         const callbacks = [];          this.then = function (onFulfilled){             return new Promise((resolve, reject)=>{                 handle({ //桥梁,将新 Promise 的 resolve 方法,放到前一个 promise 的回调对象中                    onFulfilled,                      resolve                 })             })         }          function handle(callback){             if(state === 'pending'){                 callbacks.push(callback)                 return;             }                          if(state === 'fulfilled'){                 if(!callback.onFulfilled){                     callback.resolve(value)                     return;                 }                 const ret = callback.onFulfilled(value) //处理回调                callback.resolve(ret) //处理下一个 promise 的resolve            }         }         function resolve(newValue){             const fn = ()=>{                 if(state !== 'pending')return                  state = 'fulfilled';                 value = newValue                 handelCb()             }                          setTimeout(fn,0) //基于 PromiseA+ 规范        }                  function handelCb(){             while(callbacks.length) {                 const fulfiledFn = callbacks.shift();                 handle(fulfiledFn);             };         }                  fn(resolve)     }