javascript - 如果你让一个函数异步并且什么都不改变会发生什么?
问题描述
我有一个数独板实现为 HTML 表和一个按钮,单击该按钮时使用 javascript 中的递归回溯算法解决数独板。现在我想这样做,以便您可以通过在我的递归函数中不立即更改 HTML 来查看所做的调整。我尝试使函数异步,然后调用此函数
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
像这样
for (let choice = 1; choice <= 9; choice++) {
this.boardArray[row][col] = choice;
// put delay here
await sleep(250);
currEntry.textContent = choice;
if (this.choiceOkay(row, col)) {
const solved = this.solveBoard(nextRow, nextCol);
if (solved) {
return true;
}
}
这确实给了我最初想要的行为,但仅限于董事会的一部分,然后它似乎就停止了。我删除了对 sleep 函数的调用,并尝试了它,唯一的改变是函数声明前面的“异步”,它仍然只做了板的一部分,但这次一次全部完成,没有视觉延迟。我想知道为什么让这个函数异步会导致这个逻辑错误?
提前致谢!
此外,这是我关于 Stack Overflow 的第一个问题,所以如果我需要更具体或类似的任何内容,请告诉我。
解决方案
函数前面的async关键字基本上是说:
这个函数将返回一个 Promise
您的sleep
函数已经返回 a Promise
,因此编写关键字async
是无用的。
重要的是await关键字,它基本上说:
在我的右边,可能有一个异步函数(同上一个 Promise)。等我回来再继续
如果你写了async function sleep
,但在调用时省略了await
关键字sleep
,你会在本质上抛出函数调用并且永远不会等待它的返回(因此你的代码“无延迟”运行)
如果你想要延迟,最好让你的算法保持原样,让你的算法的调用者告诉你的算法继续与否。您可以为此使用generators。(另一种可能是蹦床)。
function* runAlgo () {
for (let choice = 1; choice <= 9; choice++) {
yield; // gives control back to delayer
console.log('choice : ', choice)
// do your algo and put some yield wherever you like
}
}
// no need for async, a Promise is already returned
function sleep (t) {
return new Promise((ok, ko) => setTimeout(ok, t))
}
async function delayer () { // need for async so we can use the await keyword below
const it = runAlgo()
let next = it.next()
while (!next.done) {
await sleep(1000)
next = it.next()
}
}
delayer()
然而,解决你的板很可能会冻结你的用户界面。所以你也想在solvingBoard里面等待:
function* solveBoard () {
let i = 0
while (i < 5) { //freezes the ui if not yielding
yield i++
}
}
function* runAlgo () {
for (let choice = 1; choice <= 9; choice++) {
yield 'choice : '+choice; // gives control back to caller
yield* solveBoard()
}
}
// no need for async, a Promise is already returned
function sleep (t) {
return new Promise((ok, ko) => setTimeout(ok, t))
}
async function delayer () { // need for async so we can use the await keyword below
const it = runAlgo()
let next = it.next()
while (!next.done) {
await sleep(1000)
next = it.next()
console.log('data', next.value)
}
}
delayer()
推荐阅读
- datatables - 数据表和 YADCF - 多选过滤器
- python - 如何在 python 中运行 netstat -nb
- angular - 如何使用带有 Angular 5 和 Material Design 的 innerHtml 更新动态文本
- javascript - 连接到花式树的可排序在拖放时忘记了它的位置
- python - 自定义函数来获取数据框值的位置
- office-js - Office-js-helper
- clojure - Datomic - 动态查询函数
- c++ - Windows10 上的 VS Code + WSL 应用程序上的 CMake 扩展
- css - 如何自定义 Angular Flash 消息
- python - 如何从列表的每个元素都是元组的列表中获取元组的第 0 个索引处的最大值?