美文网首页
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