返回

链式调用!让异步代码如丝般顺滑,手写promise轻松搞定!

前端

打破回调地狱:手把手带你实现 Promise,让异步代码飞扬

前言:异步编程的痛点

在现代 Web 开发中,异步编程已成为不可或缺的一部分。然而,传统的回调地狱编写方式却让异步代码变得难以阅读和维护。回调地狱就像一层层嵌套的函数,代码可读性极低,而且容易出错。

破茧而出:Promise 的诞生

为了解决回调地狱的痛点,Promise 应运而生。Promise 是 JavaScript 中处理异步操作的利器,它可以使异步代码看起来像同步一样执行,从而解决地狱回调问题,大幅提升代码可读性。

Promise 的实现原理

Promise 是一个对象,它表示一个异步操作的最终完成或失败及其结果值。Promise 有三种状态:等待(pending)、已完成(fulfilled)和已失败(rejected)。

当一个 Promise 被创建时,它处于 pending 状态。当异步操作完成时,Promise 会从 pending 状态转变为 fulfilled 或 rejected 状态,并携带结果值。

Promise 的链式调用

Promise 支持链式调用,这使得我们可以将多个异步操作串联起来,并对每个操作的结果进行处理。链式调用的语法如下:

promise.then(function(result) {
  // 对结果进行处理
  return result;
}).then(function(result) {
  // 对处理后的结果进行进一步处理
});

手写 Promise 实现链式调用

下面我们来手写一个 Promise,并实现链式调用:

class Promise {
  constructor(executor) {
    this.state = 'pending';
    this.result = null;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (result) => {
      if (this.state !== 'pending') return;

      this.state = 'fulfilled';
      this.result = result;
      this.onFulfilledCallbacks.forEach((callback) => callback(result));
    };

    const reject = (error) => {
      if (this.state !== 'pending') return;

      this.state = 'rejected';
      this.result = error;
      this.onRejectedCallbacks.forEach((callback) => callback(error));
    };

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

  then(onFulfilled, onRejected) {
    return new Promise((resolve, reject) => {
      if (this.state === 'pending') {
        this.onFulfilledCallbacks.push(() => {
          try {
            const result = onFulfilled(this.result);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });

        this.onRejectedCallbacks.push(() => {
          try {
            const result = onRejected(this.result);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });
      } else if (this.state === 'fulfilled') {
        setTimeout(() => {
          try {
            const result = onFulfilled(this.result);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        }, 0);
      } else if (this.state === 'rejected') {
        setTimeout(() => {
          try {
            const result = onRejected(this.result);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }
    });
  }
}

实例演示

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

promise
  .then((result) => {
    console.log(result);
    return result + '!';
  })
  .then((result) => {
    console.log(result);
  });

输出:

Hello, world!
Hello, world!!

结语:

手写 Promise 的过程,让我们对 Promise 的实现原理有了更深入的理解。通过手写 Promise,我们不仅掌握了 Promise 的用法,还锻炼了我们的编程能力。希望这篇文章对大家有所帮助!

常见问题解答:

  1. Promise 和回调有什么区别?

Promise 是一种异步编程模型,它允许我们将异步操作串联起来并对结果进行处理。而回调是一种传统的异步编程方式,它需要在异步操作完成后手动调用回调函数。

  1. Promise 的状态有哪些?

Promise 有三种状态:pending(等待)、fulfilled(已完成)和 rejected(已失败)。

  1. Promise 的链式调用是如何工作的?

Promise 的链式调用通过 .then() 方法实现。每个 .then() 方法返回一个新的 Promise,它代表前一个 Promise 的结果。

  1. 如何处理 Promise 中的错误?

我们可以通过在 .then() 方法中提供第二个参数(即拒绝处理函数)来处理 Promise 中的错误。

  1. 为什么 Promise 比回调更好?

Promise 比回调更易于阅读、维护和调试,因为它提供了更清晰、更结构化的异步编程方式。