取消一个promise

场景:
发送多个请求后,当回来的数据要渲染到页面时,DOM元素被销毁了,此时如果要渲染就会报错
比如 react 在 useEffect 中请求的数据时,组件销毁

useEffect(() => {
    let dataPromise = new Promise(...);
    let data = dataPromise().then();
    // TODO 接下来处理 data,此时本组件可能已经销毁了,dom 也不存在了,所以需要在下面对 Promise 进行中断
    
    return (() => {
      // TODO 组件销毁时,对 dataPromise 进行中断或取消
    }) 
});

可以对生成的 Promise 对象进行再一次包装,返回一个新的 Promise 对象,而新的对象上被我们增加了 cancel 方法,用于取消。这里的原理就是在 cancel 方法里面去阻止 Promise 对象执行 then()方法。

function getPromiseWithCancel(originPromise) {
  let cancel = (v) => {};
  let isCancel = false;
  const cancelPromise = new Promise(function (resolve, reject) {
    cancel = e => {
      isCancel = true;
      reject(e);
    };
  });
  const groupPromise = Promise.race([originPromise, cancelPromise])
  .catch(e => {
    if (isCancel) {
      // 主动取消时,不触发外层的 catch
      return new Promise(() => {});
    } else {
      return Promise.reject(e);
    }
  });
  return Object.assign(groupPromise, { cancel });
}

// 使用如下
const originPromise = axios.get(url);
const promiseWithCancel = getPromiseWithCancel(originPromise);
promiseWithCancel.then((data) => {
  console.log('渲染数据', data);
});
promiseWithCancel.cancel(); // 取消 Promise,将不会再进入 then() 渲染数据

你可能感兴趣的:(promise前端)