说说 Promise

310 阅读1分钟

说实话已经用的很熟了,但是这个东西真的不好描述。

Promise 是什么

Promise 是异步编程的一种解决方案。

作用

解决传说中的回调地狱的问题,使代码更好维护。

用法

Promise 是ES6中新增的特性,本身是一个构造函数。接收一个函数,函数需要传入两个参数(resolve: Function, reject: Function),分别表示成功与失败的回调函数。Promise 的实例中可以用 then 响应 resolve 回调,catch 响应 reject 回调。

Promise 类常用的静态方法,resolve\reject\all\race

  • race 相当于赛跑,传入多个Promise,优先输入状态最快变化的Promise,不管结果是成功还是失败。
  • all 多个 Promise 任务同时执行。如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果。 如果有一个 Promise 任务 rejected,则只返回 rejected 任务的结果。

如何实现?

根据 Promise A+ 规范,要完整实现这个还是挺麻烦的。这些直接放一个简单版,应付面试应该够用。满足异步和then链式调用。

主要是通过三种状态,加上通过发布订阅的方式响应异步回调。

    const PENDING = "pending";
    const FULFILLED = "fulfilled";
    const REJECTED = "rejected";

    class Promise {
      constructor(executor) {
        if (!executor) return;
        this.state = PENDING;
        this._value = null;
        this._fulfilledQueues = [];
        this._rejectedQueues = [];

        let handleResolve = (value) => {
          this._value = value;
          this.state = FULFILLED;
          this._fulfilledQueues.forEach((fn) => {
            fn(value);
          });
        };
        let heandleRejected = (value) => {
          this._value = value;
          this.state = REJECTED;
          this._rejectedQueues.forEach((fn) => {
            fn(value);
          });
        };
        executor(
          (data) => {
            if (this.state !== PENDING) return;
            setTimeout(handleResolve, 0, data);
          },
          (err) => {
            if (this.state !== PENDING) return;
            heandleRejected(err);
          }
        );
      }
      then(onFulfilled, onRejected) {
        return new Promise((nextFulfilled, nextRejected) => {
          const complexFulfilled = (data) => {
            nextFulfilled(onFulfilled(data));
          };
          const complexRejected = (data) => {
            nextRejected(onRejected(data));
          };
          if (this.state === PENDING) {
            this._fulfilledQueues.push(complexFulfilled);
            this._rejectedQueues.push(complexRejected);
          } else if (this.state === FULFILLED) {
            nextFulfilled(this._value);
          } else if (this.state === REJECTED) {
            complexRejected(this._value);
          }
        });
      }
    }
    
    // 测试
    new Promise((resolve, reject) => {
      resolve(1);
    })
      .then((data) => {
        console.log(data);
        return 2;
      })
      .then((data) => {
        console.log("resolve: " + data);
      });
    //   1
    //   resolve: 2