You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改通用轮询函数以支持手动终止后台API轮询任务?

解决轮询的手动终止问题

要实现删除成功后终止轮询,核心是给轮询函数添加手动取消的能力——因为原生Promise本身无法被取消,我们需要改造函数,让它暴露一个取消方法,同时在轮询逻辑里加入终止判断。

改造通用轮询函数

修改poll函数,添加取消标识和定时器管理,返回包含Promise和取消方法的对象:

export const poll = ({
  fn = () => {},
  validate = (result) => !!result,
  interval = 1000,
  maxAttempts = 15,
}) => {
  let attempts = 1;
  let isAborted = false; // 标记是否终止轮询
  let timeoutId = null; // 保存定时器ID,用于清除

  const executePoll = async (resolve, reject) => {
    // 若已终止,直接结束并抛出取消错误
    if (isAborted) {
      return reject(new Error('Polling aborted'));
    }

    try {
      const result = await fn();
      attempts += 1;

      if (validate(result)) {
        return resolve(result);
      } else if (maxAttempts && attempts > maxAttempts) {
        return reject(new Error('Exceeded max attempts'));
      } else {
        // 保存定时器ID,方便后续清除
        timeoutId = setTimeout(executePoll, interval, resolve, reject);
      }
    } catch (error) {
      // 未终止的情况下才继续轮询
      if (!isAborted) {
        timeoutId = setTimeout(executePoll, interval, resolve, reject);
      }
    }
  };

  const pollPromise = new Promise(executePoll);

  // 暴露取消方法:标记终止+清除定时器
  const cancel = () => {
    isAborted = true;
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
  };

  return { promise: pollPromise, cancel };
};

调用轮询并实现删除终止

在页面中保存轮询实例,删除成功后调用cancel方法终止轮询:

// 全局保存当前轮询实例(如果有多个轮询,可改用Map存储对应关系)
let activePoll = null;

// 发起轮询的逻辑
function startPolling() {
  activePoll = poll({
    fn: () => api.get(url), // 你的API调用
    validate: (res) => !res?.data?.lesson_id,
    interval: 5000,
    maxAttempts: 30,
  });

  activePoll.promise
    .then((result) => {
      // 轮询成功的业务逻辑
      console.log('轮询完成:', result);
    })
    .catch((err) => {
      // 区分"主动取消"和"其他错误"
      if (err.message !== 'Polling aborted') {
        console.error('轮询失败:', err);
      }
    });
}

// 删除按钮的点击处理逻辑
async function handleDelete() {
  try {
    // 执行删除接口调用
    await api.delete(yourDeleteUrl);
    
    // 删除成功后,终止轮询
    if (activePoll) {
      activePoll.cancel();
      activePoll = null; // 清空实例,避免内存泄漏
      // 这里执行UI移除元素的逻辑
      console.log('已终止轮询并移除元素');
    }
  } catch (deleteErr) {
    console.error('删除失败:', deleteErr);
  }
}

关键说明

  • isAborted标识:每次轮询执行前都会检查这个标识,若为true则直接终止流程
  • timeoutId:保存每次setTimeout的ID,确保取消时能彻底清除定时器,阻止下一次轮询触发
  • 返回的cancel方法:让调用方可以在任意时机(比如删除成功后)主动终止轮询
  • 错误区分:在catch里判断错误信息,避免把主动取消当成异常处理

内容的提问来源于stack exchange,提问作者Priyen Mehta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:40:26