Async/Await异步异常问题:Hangman游戏word值无法正确获取
问题分析
你的判断完全正确,核心就是异步操作的执行顺序问题:
fetchWord里的fetch是异步网络请求,它的回调(.then内的逻辑)属于微任务,会排在当前主线程的所有同步代码执行完毕后才触发。- 你调用
a.fetchWord()后,主线程会立刻继续执行a.displayChoices()和document.write(a.word),此时fetch请求还未完成,this.word还未被赋值,因此页面显示undefined。 - 用
setTimeout能生效是因为它的回调属于宏任务,会在微任务执行完成后才触发,这时this.word已经被成功赋值。
修复方案
方案1:用async/await规范异步逻辑
把fetchWord改为异步方法,调用时用await等待请求完成,再执行依赖单词的逻辑:
<body> <script> class Hangman { async fetchWord(url) { const response = await fetch(url); const wordArray = await response.json(); this.word = wordArray[0]; } displayChoices() { const choices = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']; choices.forEach(choice => { const label = document.createElement('label'); label.innerText = choice; label.id = choice; const element = document.createElement('input'); element.type = 'radio'; element.value = choice; element.id = choice; label.appendChild(element); document.body.appendChild(label); }); } } (async function() { const a = new Hangman(); await a.fetchWord('https://random-word-api.herokuapp.com/word'); a.displayChoices(); // 替换document.write,用DOM元素展示单词更安全 const wordElement = document.createElement('p'); wordElement.textContent = a.word; document.body.appendChild(wordElement); })(); </script> </body>
方案2:在fetch回调内执行后续逻辑
如果不想用async/await,可以把依赖this.word的代码放到fetch的.then回调里,确保单词获取完成后再执行:
<body> <script> class Hangman { fetchWord(url) { return fetch(url) .then(data => data.json()) .then(word => { this.word = word[0]; this.displayWord(); }); } displayChoices() { const choices = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']; choices.forEach(choice => { const label = document.createElement('label'); label.innerText = choice; label.id = choice; const element = document.createElement('input'); element.type = 'radio'; element.value = choice; element.id = choice; label.appendChild(element); document.body.appendChild(label); }); } displayWord() { const wordElement = document.createElement('p'); wordElement.textContent = this.word; document.body.appendChild(wordElement); } } const a = new Hangman(); a.fetchWord('https://random-word-api.herokuapp.com/word'); a.displayChoices(); </script> </body>
额外提示
- 尽量避免使用
document.write,它在页面加载完成后调用会覆盖整个页面,用DOM操作创建元素展示内容更安全可靠。 - 建议给
fetch添加错误处理(比如.catch或try/catch),避免因网络问题导致游戏崩溃。
内容的提问来源于stack exchange,提问作者Toban Harnish
相关产品推荐
相关产品推荐

