Skip to content

promise 是否可以取消?

Posted on:2024年8月15日 at 18:38

JavaScript 中的原生 Promise 不直接支持取消操作。Promise 的设计理念是一次性且不可变的,创建后就不可取消。

实现 Promise 取消的常见方法有:

1. 使用标志位

可以在 Promise 内部设置一个取消标志,手动检查这个标志来决定是否继续执行操作。

function cancellablePromise(executor) {
  let cancelled = false;

  const promise = new Promise((resolve, reject) => {
    executor(
      (value) => {
        if (!cancelled) resolve(value);
      },
      (error) => {
        if (!cancelled) reject(error);
      },
    );
  });

  return {
    promise,
    cancel() {
      cancelled = true;
    },
  };
}

2. 使用 AbortController

对于 Fetch API 或类似支持 AbortController 的操作,可以利用 AbortController 取消网络请求。

const controller = new AbortController();
const signal = controller.signal;

fetch("url", { signal })
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((err) => {
    if (err.name === "AbortError") {
      console.log("Fetch aborted");
    } else {
      console.error("Fetch error:", err);
    }
  });

// 取消请求
controller.abort();

3. 自定义取消的 Promise 机制

通过自定义机制来处理 Promise 的取消逻辑,可以封装 Promise 和取消逻辑。

class CancelablePromise {
  constructor(executor) {
    this._isCanceled = false;
    this._promise = new Promise((resolve, reject) => {
      executor(
        (value) => !this._isCanceled && resolve(value),
        (error) => !this._isCanceled && reject(error),
      );
    });
  }

  cancel() {
    this._isCanceled = true;
  }

  then(onFulfilled, onRejected) {
    return this._promise.then(onFulfilled, onRejected);
  }

  catch(onRejected) {
    return this._promise.catch(onRejected);
  }
}

4. 使用第三方库

有些第三方库(如 Bluebirdrxjs)提供了对 Promise 取消的支持或替代方案。

原文转自:https://fe.ecool.fun/topic/848cb975-f2e8-4a46-bf55-d36acd6a1a38