JavaScript中如何将排序算法实现为generator函数 解决React排序可视化问题
React 冒泡排序可视化异常修复方案
问题根因
- 生成器实例重复创建:原代码每次循环都会重新调用
bSort生成新的生成器实例,每次仅能拿到第一次迭代的结果,因此数组仅会变更一次。 - setState批量更新:同步for循环执行速度极快,React会自动合并多次
setState操作,视图只会在循环全部结束后渲染一次最终结果。 - 数组引用未变更:生成器内直接修改传入的原数组,数组引用地址不变,React可能会判定state无变化跳过渲染。
- 无迭代间隔延迟:两次数组状态更新之间没有设置停顿时间,无法观察到排序的渐变过程。
- 调用笔误:原组件方法内误调用了自身
bubbleSorting而非引入的生成器bSort,会导致逻辑异常。
重构代码
1. 生成器函数优化
每次迭代返回新数组,不修改原数组,同时优化冒泡排序的循环边界:
export function *bSort (arr: number[]) { // 浅拷贝原数组,避免直接修改入参 const sortArr = [...arr]; const len = sortArr.length; for (let i = 0; i < len; i++) { // 末尾已排序的元素无需再次比较 for (let j = 0; j < len - 1 - i; j++) { if (sortArr[j] > sortArr[j + 1]) { const tmp = sortArr[j]; sortArr[j] = sortArr[j + 1]; sortArr[j + 1] = tmp; } // 返回浅拷贝的新数组,变更引用触发state更新 yield [...sortArr]; } } return [...sortArr]; }; export default bSort;
2. 组件排序方法优化
使用async/await实现迭代延迟,生成器仅初始化一次,避免批量更新:
首先在组件内/外部定义延迟工具函数:
// 延迟函数,单位ms const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
修改组件的排序触发方法:
bubbleSorting = async () => { // 仅初始化一次生成器实例,传入初始待排序数组 const sortGenerator = bSort(this.state.consequence); let stepResult = sortGenerator.next(); while (!stepResult.done) { // 更新数组状态触发重渲染 this.setState({ consequence: stepResult.value }); // 停顿指定时间后再执行下一次迭代,可自行调整数值控制排序速度 await delay(500); stepResult = sortGenerator.next(); } // 最终状态更新 this.setState({ consequence: stepResult.value }); };
额外优化建议
- 可新增
isSorting状态变量,排序过程中禁止重复触发排序操作,也可作为排序中断的开关。 - 可将延迟时间做成可配置项,允许用户手动调整排序动画的速度。
内容的提问来源于stack exchange,提问作者Dima
相关产品推荐
相关产品推荐

