您的当前位置:首页正文

promise原理

2024-11-23 来源:个人技术集锦

推荐一个写Promise的规范文档: 

开始实现简单版本的promise:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class Promise {
  constructor(excuctor) {
    this.status = PENDING;
    this.value = undefined; // 存放成功的值
    this.reason = undefined; // 存放失败的值
    this.fulfillCallbacks = [];
    this.rejectCallbacks = [];
    let resolve = (value) => {
      // 只有状态是等待的时候才可以转换成其他状态
      if (this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        this.fulfillCallbacks.forEach(fn => fn())
      }
    }
    let reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.rejectCallbacks.forEach(fn => fn())
      }
    }
    try {
      excuctor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected) {
    // 同步
    if (this.status === FULFILLED) {
      return onFulfilled(this.value)
    }
    // 同步
    if (this.status === REJECTED) {
      return onRejected(this.reason)
    }
    // 异步
    if (this.status === PENDING) {
      this.fulfillCallbacks.push(() => {
        onFulfilled(this.value)
      })
      this.rejectCallbacks.push(() => {
        onRejected(this.reason)
      })
    }
  }
}
module.exports = Promise

上面的实现并没有考虑then的回调中返回promise的情况,所以下面的代码会着重实现这一块逻辑

1.如果then的成功或者失败回调中返回的还是promise,会等待这个promise执行结果 并将结果传给下一个then的成功时的参数中

2.只有两种情况会走下一个then的失败回调:

   1.如果then的成功或者失败回调抛出异常 则走下一个then的失败回调

   2.如果then的成功或者失败回调返回一个失败的promise

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
//核心方法
function resolvePromise(promise2, x, resolve, reject) {
  if (x === promise2) {
    return reject(new TypeError('x 不能等于 promise2'))
  }
  if (typeof x === 'object' && x !== null) {
    try {
      let then = x.then; // 取then的时候可能发生异常 别人用Object.defineProperty定义的
      if (typeof then === 'function') {
        // 确定x是promise,然后执行这个promise
        // then.call的方式可以减少再次取x.then的值 因为可能再次取会出现问题
        then.call(x, (y) => {
          // y可能还会是promise
          // resolvePromise(promise2, y, resolve, reject) resolve的时候已经判断了
          resolve(y)
        }, (r) => {
          reject(r)
        })

      } else {
        // x是普通值
        resolve(x)
      }
    } catch (error) {
      reject(error)
    }
  } else {
    resolve(x)
  }
}
class Promise {
  constructor(excuctor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.fulfillCallbacks = [];
    this.rejectCallbacks = [];
    let resolve = (value) => {
      // 如果value是一个promise
      if (value instanceof Promise) {
        return value.then(resolve, reject)
      }
      // 只有状态是等待的时候才可以转换成其他状态
      if (this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        this.fulfillCallbacks.forEach(fn => fn())
      }
    }
    let reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.rejectCallbacks.forEach(fn => fn())
      }
    }
    try {
      excuctor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  // x 是当前then的成功或者失败回调的返回结果
  // 如果x是普通值 直接传递到下一个then中
  // 如果x是promise 需要拿到这个promise的状态
  // 执行时抛出错误直接 调用promise2的reject
  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
    // 每次调用then都需要返回一个新的实例 保证状态不影响
    let promise2 = new Promise((resolve, reject) => {
      // 同步
      if (this.status === FULFILLED) {

        setTimeout(() => {
          try {
            let x = onFulfilled(this.value)
            // resolvePromise 判断x是普通值还是promise 然后做一些操作
            resolvePromise(promise2, x, resolve, reject)
            // resolve(x) // 这种只能处理x是普通值的情况
          } catch (error) {
            reject(error)
          }
        });

      }
      // 同步
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        });

      }
      // 异步
      if (this.status === PENDING) {
        this.fulfillCallbacks.push(() => {

          setTimeout(() => {
            try {
              let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
          });

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

        })
      }
    })
    return promise2
  }
}
module.exports = Promise

promise的常用静态方法和原型方法的实现:

  1. reject:将现有对象转为 Promise 对象,状态为reject。
  2. resolve:将现有对象转为 Promise 对象,状态为resolve。
  3. all: 都成功才会resolve,有一个失败就reject
  4. race: 谁先改变状态,就返回谁的
  5. allSettled:不论每一个操作是成功还是失败,都收集起来,然后返回。它永远不会执行catch
  6. any:有一个成功就resolve,都失败才reject
  7. finally:不论成功还是失败都会执行,并且回调中如果有promise,会等待这个promise执行完,才会执行后面的操作
  8. catch:捕获错误
  static reject(error) {
    return new Promise((resolve, reject) => {
      reject(error)
    })
  }
  static resolve(value) {
    return new Promise((resolve, reject) => {
      resolve(value)
    })
  }

  static all(promises) {
    return new Promise(function (resolve, reject) {
      let results = [];
      let j = 0;
      let promisesLength = promises.length;
      for (let i = 0; i < promisesLength; i++) {
        Promise.resolve(promises[i]).then(res => {
          results[i] = res;
          // 当所有函数都正确执行了,resolve输出所有返回结果。
          if (++j === promisesLength) {
            resolve(results);
          }
        }, reject);
      }
    });

  }

  static race(promises) {
    return new Promise((resolve, reject) => {
      for (let promise of promises) {
        Promise.resolve(promise).then(resolve, reject)
      }
    })
  }

  static allSettled(promises) {
    return new Promise((resolve) => {
      let results = []
      let index = 0;
      for (let i = 0; i < promises.length; i++) {
        Promise.resolve(promises[i]).then((val) => {
          results[i] = { status: FULFILLED, value: val }
          if (++index === promises.length) { resolve(results) }
        }, err => {
          results[i] = { status: REJECTED, reason: err }
          if (++index === promises.length) { resolve(results) }
        })
      }
    })
  }

  static any(promises) {
    return new Promise((resolve, reject) => {
      let index = 0;
      let reasons = []
      for (let i = 0; i < promises.length; i++) {
        Promise.resolve(promises[i]).then(resolve, (err) => {
          reasons[i] = err
          if (++index === promises.length) {
            reject(new AggregateError(reasons))
          }
        })
      }
    })
  }
  finally(callback) {
    return this.then((val) => {
      // callback()
      // return val
      // Promise.resolve具备等待效果
      return Promise.resolve(callback()).then(() => val)
    }, (err) => {
      return Promise.resolve(callback()).then(() => {
        throw err
      })

    })
  }
  catch(errCallback) {
    return this.then(null, errCallback)
  }

 

 

显示全文