美文网首页
Promise的代码运行分析

Promise的代码运行分析

作者: zdxhxh | 来源:发表于2019-11-04 22:58 被阅读0次

    废话不多说,来分析以下Promise是怎么运行的 ?

    远古时期,我写过一篇MyPromise的实现

    这篇文章揭示了Promise就是使用oop将传统callback队列放到自己的成员变量实现而已,这篇文章缺点在于没有阐述值传透(以后填)。

    我们来剖析以下代码,在Promise内部到底做了什么?

    new Promise((resolve,reject)=> {   // p1
      setTimeout(function(){
        resolve(22)
      },1000)
    })
    .then(value=> {                     // p2
      console.log('promise2')
    })
    .then(()=>{                        // p3
      console.log('promise3')
    })
    

    我将它分为2个阶段

    一、回调函数的加载

    实际上,下面这部分代码,称为excutor

    (resolve,reject)=> { 
      setTimeout(function(){
        resolve(22)
      },1000)
    }
    

    excutor 在Promise对象创建后是立刻执行的,但众所周知,setTimeout只是将函数放进异步队列,当主线程空闲时才执行.所以

    它并不是等到异步函数执行时,才执行then的,此时已经执行then了
    它并不是等到异步函数执行时,才执行then的,此时已经执行then了
    它并不是等到异步函数执行时,才执行then的,此时已经执行then了

    它的过程如下:

    • p1的创建
    • p1.excutor (异步队列+1)
    • p1.then(cb1)
    • p2创建
    • p2.excutor()
    • p1.asyncArr.push(包装过的cb1)
    • p2.then(cb2)
    • p3创建
    • p3.excutor()
    • p2.asyncArr.push(包装过的cb2)

    二、异步任务执行

    主线程终于执行完毕了,此时

    • 异步调用
    • p1.resolve(22)
    • 包装过的cb1(它闭包保存了p2.resolve)
    • 执行原装cb1(22) ,并缓存其结果x(undefined)
    • p2.resolve(x)
    • 包装过的cb2(它闭包保存了p3.resolve)
    • 执行原装cb2(undefined) ,并缓存其结果x(undefined)
    • p3.resolve(x)
    • p3的异步数组空空如也

    这就是Promise的链式调用,通过then创建多个Promise,通过前一个Promise实例保存后一个实例的resolve,一次触发,多个受用

    两个独立的过程

    源码

    这文章的代码运行分析源码在
    https://juejin.im/post/5aa7868b6fb9a028dd4de672#heading-10

    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    
    function Promise(excutor) {
      let self = this
      this.status = PENDING
      this.value = undefined
      this.reson = undefined
      this.onFulfilledCallbacks = []
      this.onRejectedCallbacks = []
    
      function resolve(value) {
        if (value instanceof Promise) {
          return value.then()
        }
        setTimeout(() => {
          if (self.status === PENDING) {
            self.status = FULFILLED
            self.value = value
            self.onFulfilledCallbacks.forEach(cb => cb(self.value))
          }
        })
      }
    
      function reject(reson) {
        setTimeout(() => {
          if (self.status === PENDING) {
            self.status = REJECTED
            self.reson = reson
            self.onRejectedCallbacks.forEach(cb => cb(self.value))
          }
        })
      }
      try {
        excutor(resolve, reject);
      } catch (e) {
        reject(e);
      }
    }
    
    function resolvePromise(nextPromise, data, resolve, reject) {
      if (nextPromise === data) {
        return reject(new TypeError('循环引用'))
      }
      let called = false
      if (data instanceof Promise) {
        if (data.status === PENDING) {
          data.then(value => {
            resolvePromise(nextPromise, value, resolve, reject)
          }, reson => {
            reject(reson)
          })
        } else {
          data.then(resolve, reject);
        }
      } else if (data !== null && (typeof data === 'object') || (typeof data === 'function')) {
        try {
          let then = data.then
          if (typeof then === 'function') {
            then.call(data, value => {
              if (called) return
              called = true
              resolvePromise(nextPromise, value, resolve, reject)
            }, reson => {
              if (called) return
              called = true
              reject(reson)
            })
          }
        } catch (e) {
          if (called) return
          called = true
          reject(e)
        }
      } else {
        resolve(data)
      }
    }
    
    Promise.prototype.then = function (onFulfilled, onRejected) {
      const that = this;
      let nextPromise;
      // 处理参数默认值 保证参数后续能够继续执行
      onFulfilled =
        typeof onFulfilled === "function" ? onFulfilled : value => value;
      onRejected =
        typeof onRejected === "function" ? onRejected : reason => {
          throw reason;
        };
      if (that.status === FULFILLED) { // 成功态
        return nextPromise = new Promise((resolve, reject) => {
          setTimeout(() => {
            try {
              let data = onFulfilled(that.value);
              resolvePromise(nextPromise, data, resolve, reject); // 新的promise resolve 上一个onFulfilled的返回值
            } catch (e) {
              reject(e); // 捕获前面onFulfilled中抛出的异常 then(onFulfilled, onRejected);
            }
          });
        })
      }
    
      if (that.status === REJECTED) { // 失败态
        return nextPromise = new Promise((resolve, reject) => {
          setTimeout(() => {
            try {
              let data = onRejected(that.reason);
              resolvePromise(nextPromise, data, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });
      }
    
      if (that.status === PENDING) { // 等待态
        // 当异步调用resolve/rejected时 将onFulfilled/onRejected收集暂存到集合中
        return nextPromise = new Promise((resolve, reject) => {
          that.onFulfilledCallbacks.push((value) => {
            try {
              let data = onFulfilled(value);
              resolvePromise(nextPromise, data, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
          that.onRejectedCallbacks.push((reason) => {
            try {
              let data = onRejected(reason);
              resolvePromise(nextPromise,data, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });
      }
    };
    
    new Promise((resolve,reject)=> { 
      setTimeout(function(){
        resolve(22)
      },1000)
    })
    .then(value=> { 
      console.log('promise2')
    })
    .then(()=>{
      console.log('promise3')
    })
    

    相关文章

      网友评论

          本文标题:Promise的代码运行分析

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