返回

写一个自己的 Promise,从零开始

前端

对于 JavaScript 开发人员来说,Promise 是一个非常有用的工具,它可以让你处理异步操作。然而,编写自己的 Promise 可能会让人望而生畏。在这篇文章中,我将通过测试先行的方式,手把手地教你如何从零开始编写自己的 Promise。

测试先行

测试先行是一种编写代码的技巧,它涉及编写测试,然后根据测试编写代码。这有助于确保你的代码从一开始就按照预期工作。对于编写 Promise 来说,这种方法特别有用,因为它可以帮助你隔离和测试 Promise 的各个方面。

编写 Promise 的步骤

让我们按照以下步骤来编写一个 Promise:

1. 编写测试

首先,让我们编写一个简单的测试,来测试 Promise 是否可以正常解析。

it('should resolve', () => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve('成功!');
    }, 1000);
  });

  return expect(promise).resolves.toBe('成功!');
});

2. 实现 Promise

接下来,让我们实现一个最简单的 Promise,它只包含 resolve 方法。

class Promise {
  constructor(executor) {
    this.executor = executor;
    this.state = 'pending';
    this.value = undefined;
  }

  resolve(value) {
    this.state = 'fulfilled';
    this.value = value;
  }
}

3. 添加 then 方法

then 方法用于处理 Promise 的结果。让我们添加一个 then 方法到我们的 Promise 类:

then(onFulfilled) {
  return new Promise((resolve) => {
    this.executor((value) => {
      const result = onFulfilled(value);
      resolve(result);
    });
  });
}

4. 处理 rejected Promise

Promise 还可以被 rejected,这意味着操作失败。让我们添加一个 catch 方法来处理这种情况:

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

5. 添加 finally 方法

finally 方法始终在 Promise 完成后执行,无论 Promise 是 resolved 还是 rejected。让我们添加一个 finally 方法:

finally(onFinally) {
  return this.then(onFinally, onFinally);
}

完整代码

以下是完整 Promise 实现的代码:

class Promise {
  constructor(executor) {
    this.executor = executor;
    this.state = 'pending';
    this.value = undefined;
  }

  resolve(value) {
    this.state = 'fulfilled';
    this.value = value;
  }

  then(onFulfilled) {
    return new Promise((resolve) => {
      this.executor((value) => {
        const result = onFulfilled(value);
        resolve(result);
      });
    });
  }

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

  finally(onFinally) {
    return this.then(onFinally, onFinally);
  }
}

使用 Promise

现在我们已经实现了自己的 Promise,让我们看看如何使用它:

const promise = new Promise((resolve) => {
  setTimeout(() => {
    resolve('成功!');
  }, 1000);
});

promise.then((value) => {
  console.log(value); // 输出:成功!
});

总结

在本文中,我们通过测试先行的方式一步一步地实现了自己的 Promise。我们涵盖了 Promise 的基本功能,包括 resolvethencatchfinally 方法。你现在应该对 Promise 的内部工作原理有了更深入的理解,并且可以自信地编写自己的 Promise 来处理异步操作。