等待异步函数中止时禁用按钮的可扩展实现方案
我如何在等待Promise函数sort中止时禁用按钮?目前我通过设置delay实现该功能,在排序50条左右的数据时效果良好,但处理更大数据量时失效。请问如何实现可扩展的方案,使其适配所有数据集大小?
解决方案
问题出在你依赖固定时长的delay(500)等待排序中止,但大数据集下排序函数可能需要更长时间响应中止信号。正确的做法是**等待排序Promise实际完成(无论是正常结束还是中止)**后再重置按钮状态,而非依赖固定延迟。
核心改进点
- 跟踪当前排序的Promise实例,确保等待它完全结束后再更新按钮
- 统一按钮状态重置逻辑,避免重复代码
- 使用状态变量防止重复点击干扰
修订后的代码
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
相关产品推荐
相关产品推荐

