返回

Promise 实现原理剖析:精简高效的代码解析

前端

前言

Promise 是 JavaScript 中处理异步编程的利器,它可以帮助我们编写更易读、更易维护的代码。然而,很多同学在学习 Promise 时,知其然却不知其所以然,对其中的用法理解不了。

本系列文章将由浅入深逐步实现 Promise,并结合流程图、实例以及动画进行演示,达到深刻理解 Promise 用法的目的。

本文适合对 Promise 的用法有所了解的人阅读,如果还不清楚,请自行查阅相关资料。

Promise 的基础实现

首先,我们来看一个最简单的 Promise 实现:

class Promise {
  constructor(executor) {
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  resolve(value) {
    if (this.state !== 'pending') return;

    this.state = 'fulfilled';
    this.value = value;

    this.onFulfilledCallbacks.forEach(callback => callback(value));
  }

  reject(reason) {
    if (this.state !== 'pending') return;

    this.state = 'rejected';
    this.reason = reason;

    this.onRejectedCallbacks.forEach(callback => callback(reason));
  }

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };

    const promise2 = new Promise((resolve, reject) => {
      if (this.state === 'pending') {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (err) {
              reject(err);
            }
          }, 0);
        });

        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (err) {
              reject(err);
            }
          }, 0);
        });
      } else if (this.state === 'fulfilled') {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        }, 0);
      } else if (this.state === 'rejected') {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        }, 0);
      }
    });

    return promise2;
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(onFinally) {
    return this.then(value => {
      onFinally();
      return value;
    }, reason => {
      onFinally();
      throw reason;
    });
  }
}

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise!'));
  }

  if (x instanceof Promise) {
    x.then(value => {
      resolvePromise(promise2, value, resolve, reject);
    }, reason => {
      reject(reason);
    });
  } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
    try {
      const then = x.then;
      if (typeof then === 'function') {
        then.call(x, value => {
          resolvePromise(promise2, value, resolve, reject);
        }, reason => {
          reject(reason);
        });
      } else {
        resolve(x);
      }
    } catch (err) {
      reject(err);
    }
  } else {
    resolve(x);
  }
}

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Hello, world!');
  }, 2000);
});

promise.then(value => {
  console.log(value); // 'Hello, world!'
});

这个 Promise 实现非常简单,它只有最基本的功能,但它已经足够让我们理解 Promise 的工作原理。

Promise 的状态

Promise 有三种状态:

  • pending :表示 Promise 还未完成,即还没有调用 resolvereject 方法。
  • fulfilled :表示 Promise 已完成,并且成功执行了 resolve 方法。
  • rejected :表示 Promise 已完成,并且执行了 reject 方法。

Promise 的方法

Promise 有以下几个方法:

  • resolve(value) :将 Promise 的状态改为 fulfilled ,并传入一个值。
  • reject(reason) :将 Promise 的状态改为 rejected ,并传入一个原因。
  • then(onFulfilled, onRejected) :在 Promise 完成时执行指定的回调函数。如果 Promise 的状态是 fulfilled ,则执行 onFulfilled 函数;如果 Promise 的状态是 rejected ,则执行 onRejected 函数。
  • catch(onRejected) :在 Promise 完成时执行指定的回调函数。如果 Promise 的状态是 fulfilled ,则忽略该回调函数;如果 Promise 的状态是 rejected ,则执行该回调函数。
  • finally(onFinally) :在 Promise 完成时执行指定的回调函数。无论 Promise 的状态是 fulfilled 还是 rejected ,都会执行该回调函数。

Promise 的使用示例

以下是一个 Promise 的使用示例:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Hello, world!');
  }, 2000);
});

promise.then(value => {
  console.log(value); // 'Hello, world!'
});

在这个示例中,我们首先创建了一个 Promise 对象,然后在 2 秒后调用 resolve 方法,将 Promise 的状态改为 fulfilled ,并传入一个值 "Hello, world!"。然后,我们使用 then 方法添加了一个回调函数,该回调函数将在 Promise 完成时执行。当 Promise 完成时,回调函数被执行,并且将 "Hello, world!" 打印到控制台。

总结

本文介绍了 Promise 的基础实现,包括 Promise 的状态、方法和使用示例。希望通过本文,你能够对 Promise 有一个更深入的理解。