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

等待异步函数中止时禁用按钮的可扩展实现方案

我如何在等待Promise函数sort中止时禁用按钮?目前我通过设置delay实现该功能,在排序50条左右的数据时效果良好,但处理更大数据量时失效。请问如何实现可扩展的方案,使其适配所有数据集大小?

解决方案

问题出在你依赖固定时长的delay(500)等待排序中止,但大数据集下排序函数可能需要更长时间响应中止信号。正确的做法是**等待排序Promise实际完成(无论是正常结束还是中止)**后再重置按钮状态,而非依赖固定延迟。

核心改进点

  1. 跟踪当前排序的Promise实例,确保等待它完全结束后再更新按钮
  2. 统一按钮状态重置逻辑,避免重复代码
  3. 使用状态变量防止重复点击干扰

修订后的代码

let isSorting = false;
let controller = new AbortController();
let currentSortPromise = null;

// 重置按钮到初始状态的辅助函数
function resetButtonToIdle() {
  startButton.textContent = 'Start';
  startButton.style.backgroundColor = 'green';
  startButton.disabled = false;
  startButton.style.cursor = 'pointer';
}

startButton.addEventListener('click', async () => {
  if (isSorting) {
    // 进入中止流程
    isSorting = false;
    // 立即禁用按钮并显示等待状态
    startButton.disabled = true;
    startButton.textContent = 'Wait ...';
    startButton.style.backgroundColor = 'grey';
    startButton.style.cursor = 'not-allowed';
    
    // 触发中止信号
    controller.abort();
    
    // 等待排序Promise完全结束(无论成功还是中止)
    try {
      await currentSortPromise;
    } catch (err) {
      // 忽略中止错误(已在启动流程的catch中处理)
      if (!(err instanceof DOMException && err.name === 'AbortError')) {
        throw err;
      }
    }
    
    // 重置按钮和控制器
    resetButtonToIdle();
    controller = new AbortController();
  } else {
    // 进入排序启动流程
    isSorting = true;
    // 更新按钮为停止状态
    startButton.textContent = 'Stop';
    startButton.style.backgroundColor = 'red';
    startButton.style.cursor = 'pointer';
    
    try {
      const sort = SelectAlgorithm(data, algorithmType);
      // 保存当前排序的Promise实例
      currentSortPromise = sort(updateBars, controller.signal);
      await currentSortPromise;
      // 排序完成后重置条形图颜色
      svg.selectAll('rect').style('fill', 'black');
    } catch (err) {
      if (err instanceof DOMException && err.name === 'AbortError') {
        console.log('Sorting function aborted');
      } else {
        throw err;
      }
    } finally {
      // 无论排序成功还是中止,最终都重置状态
      resetButtonToIdle();
      controller = new AbortController();
      isSorting = false;
      currentSortPromise = null;
    }
  }
});

关键解释

  • currentSortPromise: 存储当前正在执行的排序Promise,确保我们能等待它完全结束,而非依赖固定延迟
  • resetButtonToIdle: 统一按钮状态重置逻辑,避免重复代码
  • 中止流程中的await currentSortPromise: 确保只有在排序函数真正响应中止信号并结束后,才会重置按钮状态,适配任何数据集大小
  • finally块: 在排序启动流程中,无论排序正常完成还是被中止,都会执行状态重置,保证按钮状态始终正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:25:55