JavaScript中如何让程序等待10ms执行TryNumber且不破坏数独求解逻辑
问题原因
setTimeout属于异步宏任务,你把逻辑写在setTimeout回调中时,外层同步运行的while循环不会等待回调执行,会瞬间往任务队列塞大量延迟任务。等10ms后回调集中执行时,共享的i、j、number变量已经被循环修改到了最终值,所有回调拿到的都是同一个变量的引用,逻辑完全错乱,才会出现全为1的异常结果。- 你虽然给
SolveSudoku加了async修饰,但没有使用await等待异步任务执行,函数会直接返回尚未计算完成的数独数组,外层点击回调拿到的也是未完成的结果。
修复方案
- 先新增一个延迟工具函数,用来实现可等待的定时效果:
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
- 修改
SolveSudoku中的循环逻辑,将原本写在setTimeout回调里的代码移到外层,每次循环前用await等待10ms:
async function SolveSudoku(sudoku, sudokuID) { let filledNumbers = GetFilledNumbers(sudoku); let number, i, j; let backtracked = []; for (let i = 0; i < 9; i++) { for (let j = 0; j < 9; j++) { temp = '#sudoku' + i + j; sudokuID[i][j] = document.querySelector(temp); } } for (i = 0; i < 9; i++) { for (j = 0; j < 9; j++) { number = 0; while (filledNumbers[i][j] == false) { // 等待10ms再执行后续逻辑 await delay(10); if (number < 9) number++; else { sudoku[i][j] = 0; backtracked = Backtrack(i, j, filledNumbers); i = backtracked[0]; j = backtracked[1]; number = sudoku[i][j] + 1; } if (number <= 9 && TryNumber(sudoku, i, j, number)) { sudoku[i][j] = number; sudokuID[i][j].classList.remove("border-red"); sudokuID[i][j].classList.add("border-green"); break; } sudoku[i][j] = number; sudokuID[i][j].textContent = number; sudokuID[i][j].classList.add("border-red"); } } } return sudoku; }
- 修改button2的点击回调,用
async修饰回调函数,通过await等待数独求解完成再更新界面:
button2.addEventListener('click', async function () { solvedSudoku = await SolveSudoku(sudoku, sudokuID); for (let i = 0; i < 9; i++) { for (let j = 0; j < 9; j++) { sudokuID[i][j].textContent = solvedSudoku[i][j]; } } })
修改后即可实现每步尝试数字前等待10ms、界面同步更新的效果,求解逻辑也会正常运行。
内容的提问来源于stack exchange,提问作者jonas lemineur
相关产品推荐
相关产品推荐

