返回

TS与class构建简易Promise,揭开异步编程面纱

前端

Promise,一个神奇的 JavaScript 对象,它能让你处理异步操作变得更加轻松。它提供了 then 和 catch 方法,允许你在异步操作成功或失败时执行不同的操作。使用Promise,你可以避免回调地狱,让你的代码更加易读和可维护。

现在,我们来使用 TypeScript 和 class 来实现一个简易的Promise。我们首先定义一个Promise类:

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

    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.value);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });
        this.onRejectedCallbacks.push(() => {
          try {
            const result = onRejected(this.reason);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });
      } else if (this.state === 'fulfilled') {
        setTimeout(() => {
          try {
            const result = onFulfilled(this.value);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        }, 0);
      } else if (this.state === 'rejected') {
        setTimeout(() => {
          try {
            const result = onRejected(this.reason);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }
    });
  }

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

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

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

    setTimeout(() => {
      this.onFulfilledCallbacks.forEach(callback => callback());
    }, 0);
  }

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

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

    setTimeout(() => {
      this.onRejectedCallbacks.forEach(callback => callback());
    }, 0);
  }
}

这个Promise类的构造函数接收一个executor函数作为参数,executor函数有两个参数,分别是resolve和reject。resolve函数用于将Promise的状态从pending变为fulfilled,并传入一个参数value。reject函数用于将Promise的状态从pending变为rejected,并传入一个参数reason。

Promise类还定义了then方法、catch方法、resolve方法和reject方法。then方法用于为Promise添加回调函数,当Promise的状态改变时,这些回调函数就会被执行。catch方法用于为Promise添加一个错误处理回调函数,当Promise被reject时,这个回调函数就会被执行。resolve方法用于将Promise的状态从pending变为fulfilled,并传入一个参数value。reject方法用于将Promise的状态从pending变为rejected,并传入一个参数reason。

现在,我们就可以使用这个Promise类来实现异步操作了。例如,我们可以使用Promise来实现一个简单的AJAX请求:

const promise = new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://example.com/api/data');
  xhr.onload = () => {
    if (xhr.status === 200) {
      resolve(xhr.responseText);
    } else {
      reject(xhr.statusText);
    }
  };
  xhr.onerror = () => {
    reject(xhr.statusText);
  };
  xhr.send();
});

promise.then(data => {
  console.log(data);
}).catch(error => {
  console.log(error);
});

这个代码首先创建一个Promise对象,然后使用XMLHttpRequest对象发送一个AJAX请求。当AJAX请求成功时,Promise的状态会变成fulfilled,并且将请求到的数据作为参数传递给then方法的回调函数。当AJAX请求失败时,Promise的状态会变成rejected,并且将错误信息作为参数传递给catch方法的回调函数。

使用Promise,你可以轻松地处理异步操作,让你的代码更加易读和可维护。现在,你已经学会了如何使用TypeScript和class来实现一个简易的Promise,你可以用它来构建更强大的异步应用程序。