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

async await实现归并排序可视化时绘制停顿失效该如何解决

原代码停顿失效的核心原因

你当前的归并排序逻辑是同步递归执行的,async/await只会暂停当前async函数的执行流,不会阻塞外层同步代码:

  1. 普通函数调用async函数时不会自动等待,merger里调用mergeDraw没有加await,会直接返回继续执行后续合并逻辑
  2. 所有合并操作会在几毫秒内全部跑完,所有绘制任务同步触发,自然看不到分步停顿的效果

更适合可视化的实现方案:任务队列+定时调度

这个方案不需要修改归并排序的核心逻辑,把排序计算和渲染完全分离,稳定性更高,调整节奏也更简单。

实现步骤

  1. 先定义全局的绘制任务队列和动画间隔配置
// 存储所有合并步骤的绘制任务
const drawQueue = [];
// 两次绘制的停顿时间,单位ms,可根据需求调整
const DRAW_INTERVAL = 100;
  1. 修改merger函数,将绘制逻辑改成收集任务

注意要深拷贝数组,避免后续排序操作修改数组引用,导致所有绘制任务都用最终排序完成的数组

function merger(arr1, arr2) {
  let i = 0,j = 0,mergedArr = [];
  while (i < arr1.length && j < arr2.length) {
    if (arr1[i][0] > arr2[j][0]){
      mergedArr.push(arr2[j]);
      j++;
    } else{
      mergedArr.push(arr1[i]);
      i++;
    }
  }
  while (i < arr1.length) {
    mergedArr.push(arr1[i]);
    i++;
  }
  while (j < arr2.length) {
    mergedArr.push(arr2[j]);
    j++;
  }

  var lowest = mergedArr[0][1];
  for( num = 1; num < mergedArr.length; num++){
    if(mergedArr[num][1] < lowest){
        lowest = mergedArr[num][1];
    }
  }

  // 原mergeDraw调用改为推入任务队列,深拷贝数组
  drawQueue.push({
    data: JSON.parse(JSON.stringify(mergedArr)),
    startPoint: lowest
  });

  return mergedArr;
}
  1. 剥离mergeDraw的异步逻辑,只保留纯绘制功能
function mergeDraw(anArray,startPoint){
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  // 按需添加清屏逻辑,不需要保留历史绘制轨迹就保留这行
  ctx.clearRect(0, 0, c.width, c.height);
  let j = startPoint;

  for(let num = 0; num < anArray.length; num++){
    anArray[num][1] = j;

    ctx.lineWidth = 3.2 ;
    ctx.strokeStyle = 'seagreen'
    ctx.beginPath();
    ctx.moveTo(j, 0);
    ctx.lineTo(j, 800);
    ctx.stroke();

    ctx.lineWidth = 3;
    ctx.strokeStyle = 'black'
    ctx.beginPath(); 
    ctx.moveTo(j, 0);
    ctx.lineTo(j, anArray[num][0]);
    ctx.stroke();

    j+=8;
  }
}
  1. 编写动画调度函数,按顺序执行队列里的绘制任务
function startAnimation() {
  // 队列空就结束动画
  if(drawQueue.length === 0) return;
  // 取出第一个任务执行绘制
  const task = drawQueue.shift();
  mergeDraw(task.data, task.startPoint);
  // 停顿指定时间后执行下一个任务
  setTimeout(startAnimation, DRAW_INTERVAL);
}
  1. 触发排序和动画的逻辑调整
// 先执行完整的归并排序,生成所有绘制任务
mergeSort(你的待排序原始数组);
// 再启动逐帧动画
startAnimation();

内容的提问来源于stack exchange,提问作者Kenneth Lamar Cole

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:36:04