如何让JavaScript函数等待异步答题校验结果后执行棋子移动?
你卡到了异步操作的经典坑点——你的getQuestion()里用了AJAX,这是异步执行的,所以当你写if(getQuestion())时,getQuestion()会立刻执行完毕(此时AJAX请求还在后台跑,函数实际返回undefined),根本等不到答题结果返回,自然没法触发后续的棋子移动逻辑。
我给你两种靠谱的解决方案,都是基于Promise来处理异步流程的,你可以选一种适合你的:
方案一:用Promise + .then()处理
首先重构getQuestion()函数,让它返回一个Promise,这样我们就能等待答题结果:
function getQuestion() { // 保留你原来展示问题的逻辑(比如渲染表单到#ajax-panel) // 返回Promise对象,用来包裹异步的AJAX请求 return new Promise((resolve, reject) => { // 用.one()绑定提交事件,避免重复绑定导致多次触发 $(document).one("submit","form#ajax-panel", function(event){ event.preventDefault(); const dataObj2 = { answer: $("#answer option:selected").val(), answerWriten: $("#answerWrite").val(), correctAnswer: $("#correctAnswer").val(), difficulty: $("#questionDifficulty").val(), }; console.log(dataObj2); $.ajax({ url: 'ajax/checkAnswer.php', type: 'POST', dataType: 'json', data: dataObj2, }) .done(function(data2) { console.log("Checking step completed"); $('#ajax-panel').empty(); if (data2.answer === data2.correct) { console.log("true"); $('#ajax-panel').append("<p>Točno!</p>"); resolve(true); // 答题正确,通知Promise返回true } else { console.log("false"); $('#ajax-panel').append("<p>Netočno!</p>"); resolve(false); // 答题错误,通知Promise返回false } }) .fail(function(error) { console.error("答题验证请求失败:", error); $('#ajax-panel').empty().append("<p>Došlo je do greške prilikom provjere odgovora!</p>"); reject(error); // 请求失败时触发reject,用于捕获错误 }); }); }); }
然后修改你的点击触发逻辑,用.then()等待答题结果返回后再执行移动:
// 替换成你实际触发移动的按钮选择器 $(".move-trigger-button").on("click", function() { getQuestion() .then(isAnswerCorrect => { if (isAnswerCorrect) { // 答题正确,执行棋子移动 greenPieces[i].moveSmart(diceResult); } else { // 答题错误,可添加提示或直接跳过 console.log("Odgovor je netočan, figura se ne pomiče!"); } }) .catch(error => { // 处理请求失败的情况 console.error("Greška:", error); }); });
方案二:用async/await(更接近同步代码的写法)
如果你觉得链式的.then()看着别扭,可以用async/await语法,代码会更清爽:
getQuestion()的重构和方案一完全一样,只需要修改点击事件的处理函数为async函数:
$(".move-trigger-button").on("click", async function() { try { // await会等待Promise的结果返回 const isAnswerCorrect = await getQuestion(); if (isAnswerCorrect) { greenPieces[i].moveSmart(diceResult); } else { console.log("Odgovor je netočan, figura se ne pomiče!"); } } catch (error) { console.error("Greška prilikom provjere odgovora:", error); } });
为什么原来的方法不行?
你之前的getQuestion()里,return true/false是写在AJAX的.done()回调里的——这个return只属于那个回调函数,根本不会成为getQuestion()的返回值。AJAX是异步的,当你调用getQuestion()时,浏览器会立刻发送请求,但函数本身会直接执行完,返回undefined,所以你的if(getQuestion())永远是if(undefined)(等价于false),自然不会触发移动逻辑。
用Promise的话,我们把异步操作的结果通过resolve()传递出来,再用.then()或者await等待这个结果,就能保证只有在答题结果明确后,才会判断是否移动棋子。
内容的提问来源于stack exchange,提问作者Antonio Mikulić

