首页 > 解决方案 > 如何使用 setTimeout 逐行执行 for 循环?

问题描述

我试图可视化一个冒泡排序算法,我试图找出一种方法让我的 for 循环每 1000 毫秒迭代一次,所以它会逐步执行,并且我能够绘制每次迭代的结果。

我尝试过使用 setTimeout,但是当 setTimeout 异步执行时,for 循环继续执行。还有另一种方法可以“逐步”通过 for 循环吗?

// bubble sort
function bubbleSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length; j++) {
      if (arr[j] > arr[j + 1]) {
        let temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
        delay();
      }
    }
  }
  return arr;
}
function delay() {
  setTimeout(() => {
    console.log('hello');
  }, 1000);
}

标签: javascriptalgorithmsortinganimationsettimeout

解决方案


您可以将函数转换为生成器函数,并在每次排序后生成数组的状态。

如果你尝试调用.next().value,当外循环结束时,会抛出异常。这是您可以捕获它并取消间隔的地方。

console.log('START');

let arr = [ 5, 3, 4, 2, 1 ],
    gen = bubbleSort(arr),
    wait = 1000,
    counter = 0;

const intervalId = setInterval(() => {
  try {
    const value = gen.next().value.join(',');
    console.log(`Step ${++counter}: ${value}`);
  } catch (e) {
    clearInterval(intervalId);
    console.log('STOP');
  }
}, wait);

function* bubbleSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length; j++) {
      if (arr[j] > arr[j + 1]) {
        let temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
        yield arr;
      }
    }
  }
}
.as-console-wrapper { top: 0; max-height: 100% !important; }


或者,您可以尝试添加一个启动超时的回调,该超时将以线性方式返回。

let arr = [ 5, 3, 4, 2, 1 ], wait = 1000;

const stepFn = (step, arr) => {
  const finalStep = Math.pow(arr.length, 2) - 1;
  const result = arr.join(','); // Capture values
  setTimeout(() => {
    console.log(`Step ${step}: ${result}`); // Finally display them
    if (step === finalStep) { console.log('STOP'); }
  }, step * wait); // Asynchronous calls, but the timeout is linear
};

console.log('START');
bubbleSort(arr, stepFn);

function bubbleSort(arr, callback) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length; j++) {
      if (arr[j] > arr[j + 1]) {
        let temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
      callback(i * arr.length + j, arr); // Insert a callback
    }
  }
}
.as-console-wrapper { top: 0; max-height: 100% !important; }


推荐阅读