Promise之实现自己的promise③

135 阅读2分钟

这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

原生promise.then链式调用的特点

  • 1.通过return传递结果

image.png

  • 2.通过新的promise resolve结果

image.png

  • 3.通过新的promise reject原因

image.png

  • 4.then走了失败的回调函数后,在走then

image.png

  • 5.then中使用throw new Error, 会走到下一个then失败的回调函数中去

image.png

  • 6.用catch捕获异常 catch在Promise的源码层面上就是一个then, Catch也是遵循then的运行原则

image.png

从上面可以得出以下结论

  • 成功的条件
    • then return 普通的JavaScript value
    • then return 新的promise成功态的结果 value
  • 失败的条件
    • then return 新的promise的失败态的原因 reason
    • then 抛出了异常 throw new Error
  • promise 链式调用
    • return new Promise
let promise2 = promise.then((value) => {
  // return 第一次返回的新的promise结果
}).then((value) => {
  // return 第二次返回的新的promise结果
})
// 这两种是有区别的-----------------------
let promise2 = promise.then(() => {
  // return 第一次返回的新的promise结果
})
// 第一次then返回的新的promise结果
promise2.then(() => {

})

实现promise.then

  • 实现promise.then的链式调用

image.png promise.then返回的是一个新的Promise,需要定义一个新的Promise实例。

  • 在新的实例里面进行处理,实例的resolve和reject有一个返回值x,x可能是一个普通的值或者一个新的Promise,所以需要对x进行处理,定义函数resolvePromise
  • 也需要对异常进行处理。 详细的需求可见Promise/A+, 按照文档规范来 The Promise Resolution Procedure
/**
 * @description 判单x是否是一个promise,如果是promise,需要进行特殊的处理,如果不是,需要resolve,reject
 * @param {*} promise2
 * @param {*} x
 * @param {*} resolve
 * @param {*} reject
 * @return {*}
 */  
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('TypeError: Chaining cycle detected for promise #<MyPromise>'))
  }

  let called = false; // 是否调用

  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    try {
      let then = x.then // throw error
      // 通过判断then是不是一个function来判断是否是promise
      if (typeof then === 'function') { // promise
        then.call(x, (y) => {
          if (called) return
          called = true
          // 递归调用,处理一直resolve新的promise实例
          resolvePromise(promise2, y, resolve, reject) // 处理问题1
        }, (r) => {
          if (called) return
          called = true
          reject(r)
        })
      } else {
        resolve(x) // 如果不是一个promise,直接resolve
      }
    } catch (e) {
      if (called) return
      called = true
      reject(e)
    }
  } else {
    resolve(x)
  }
}

image.png

详细代码见github地址