JavaScript ------ Promise原理及简单实现

发布于:2023-01-04 ⋅ 阅读:(256) ⋅ 点赞:(0)

在ES6中推出了新的类方法,用于解决跨域之间的参数传递----Promise。

       Promise的创建时需要传入两个回调函数(ResolveReject),并且函数在Promise对象被创建时立马调用,当程序代码运行结果满足预设的条件时,回调Resolve方法,当程序代码的运行结果不满足预设条件时,回调Reject方法返回Promise对象,对象中有then、catch、finally方法,当用户对Promise对象调用then方法时,传入两个回调函数,第一个回调函数对应Promise内Resolve函数被调用时执行,第二个函数对应Promise内Reject函数被调用时执行,同时调用then方法时返回新的Promise对象,对应回调函数的返回值赋值给新Promise对象的value,实现链式调用,若在then链式前Promise对象的Reject函数被调用,则将Promise的状态交由then新返回的Promise管理。

      同时Promise还提供了Catch方法,用于捕获Reject被调用时回调的方法,同时返回新的Promise对象,并将回调函数执行的结果传递给新Promise对象的value,如果then中有对Reject函数进行了回调,则catch方法不会执行回调函数。

       Promise中还提供了Finally方法,无论Promise中的then、catch方法执行的结果如何,都会调用的方法,同时返回新的Promise对象,将finally中函数执行的结果传递给新Promise的value,实现链式调用。

       根据Promise的功能特性,手实现简单的Promise。

// 了解Promise的3个状态  pending、fulfilled、reject
const PROMISE_STATUS_PENDING = 'PROMISE_STATUS_PENDING';
const PROMISE_STATUS_FULFILLED = 'PROMISE_STATUS_FULFILLED';
const PROMISE_STATUS_REJECT = 'PROMISE_STATUS_REJECT';

// 状态错误捕获
function executorWithErr(executor, value, resolve, reject) {
  try {
    const result = executor(value);
    resolve(result);
  } catch (error) {
    reject(error)
  }
}

class WtPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledFns = [];
    this.onRejectFns = [];

    // Fulfilled状态执行
    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        // 添加微任务,获取回调方法
        queueMicrotask(() => {
          if (this.status != PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_FULFILLED;
          this.value = value;
          this.onFulfilledFns.forEach(fn => fn(value))
        })

      }
    }
    // Reject状态执行
    const reject = (reason) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status != PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_REJECT;
          this.reason = reason;
          this.onRejectFns.forEach(fn => fn(reason))
        })
      }
    }

    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  // 调用then方法,返回新promise
  then(onFulfilled, onReject) {
    const defaultReject = err => {
      throw err
    };
    onReject = onReject || defaultReject;
    const defaultonFulfilled = value => {
      return value
    };
    onFulfilled = onFulfilled || defaultonFulfilled;

    return new WtPromise((resolve, reject) => {
      if (this.status !== PROMISE_STATUS_PENDING) {
        if (onFulfilled) executorWithErr(onFulfilled, this.value, resolve, resolve);
        if (onReject) executorWithErr(onReject, this.reason, resolve, resolve);
      }
      if (this.status === PROMISE_STATUS_PENDING && onFulfilled) {
        this.onFulfilledFns.push(() => {
          executorWithErr(onFulfilled, this.value, resolve, reject)
        })
      }
      if (this.status === PROMISE_STATUS_PENDING && onReject) {
        this.onRejectFns.push(() => {
          executorWithErr(onReject, this.reason, resolve, reject)
        })
      }
    })
  }

  catch (onReject) {
    return this.then(undefined, onReject)
  };

  finally(onfinally) {
    this.then(() => {
      onfinally()
    }, () => {
      onfinally()
    })
  }

  static resolve(value) {
    return new WtPromise(resolve => resolve(value))
  }

  static reject(reason) {
    return new WtPromise((resolve, reject) => reject(reason))
  }

  static all(...promises) {
    // 有reject被调用则直接调用reject方法,否则需等待所有的Resolve执行后在执行Resolve
    return new WtPromise((resolve, reject) => {
      const values = [];
      promises.forEach(promise => {
        promise.then(value => {
          values.push(value);
          if (values.length === promises.length) {
            resolve(values)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }

  static allSelter(...promises) {
    return new WtPromise((resolve, reject) => {
      const reslult = [];
      promises.forEach(promise => {
        promise.then(value => {
          reslult.push({
            status: PROMISE_STATUS_FULFILLED,
            value: value
          });
          if (reslult.length === promises.length) {
            resolve(reslult)
          }
        }, err => {
          reslult.push({
            status: PROMISE_STATUS_REJECT,
            value: err
          });
          if (reslult.length === promises.length) {
            resolve(reslult)
          }
        })
      })
    })
  }
  // 竞赛输出
  static race(...promises) {
    return new WtPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
      })
    })
  }
  // 等待正确输出,否则错误集合.errors
  static any(...promises) {
    return new WtPromise((resolve, reject) => {
      const errs = [];
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          errs.push(err);
          if (errs.length === promises.length) {
            reject(new AggregateError(errs))
          }
        })
      })
    })
  }
}

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到