promise原理

7 篇文章 0 订阅

推荐一个写Promise的规范文档:Promises/A+ 

  1. promise是一个类,接受一个executor函数:
  2. 有三个状态 pendding(默认)、 fulfilled 、rejected
  3. new的时候,executor 是立即执行的 如果内部出错了 就会变成失败态
  4. 状态可以由pending变成fulfilled或者rejected,但是不能将fulfilled和rejected转换成其他状态
  5. 当状态为fulfilled会执行then的成功回调,当状态为rejected会执行then的失败回调

开始实现简单版本的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)
  }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Promise是一种用于处理异步操作的JavaScript对象。它的原理是基于事件循环和回调函数的机制。当我们创建一个Promise实例时,它会立即执行一个传入的函数,并返回一个Promise对象。这个函数又被称为executor函数,它接受两个参数resolve和reject。resolve函数用于将Promise的状态从pending变为fulfilled,并传递一个值作为结果;reject函数用于将Promise的状态从pending变为rejected,并传递一个原因作为错误信息。 在executor函数中,我们可以通过调用resolve和reject来改变Promise的状态。当某个异步操作成功完成时,我们可以调用resolve来将Promise状态变为fulfilled,并传递异步操作的结果。而当某个异步操作失败时,我们可以调用reject来将Promise状态变为rejected,并传递一个错误原因。 Promise的优点之一是可以链式调用。通过在Promise对象上调用then方法,我们可以注册回调函数来处理Promise的结果。当Promise的状态从pending变为fulfilled时,将会执行与then方法关联的回调函数,并将Promise的结果作为参数传递给回调函数。当Promise的状态从pending变为rejected时,将会执行与catch方法关联的回调函数,并将错误原因作为参数传递给回调函数。通过链式调用then方法,我们可以将多个异步操作串联起来,形成一个异步操作的流水线。 总结起来,Promise原理是通过executor函数、resolve函数和reject函数来实现异步操作的封装和处理。通过链式调用then方法,可以对Promise的结果进行处理和传递。而Promise的状态变化是基于事件循环和回调函数的机制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [这一次,彻底弄懂 Promise 原理](https://blog.csdn.net/weixin_30881367/article/details/101419505)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值