为何getLogin函数return返回undefined?异步请求问题排查
问题原因与解决方法
问题原因
这段代码的核心问题是XMLHttpRequest的异步特性。调用getLogin()时,代码执行流程如下:
- 初始化
res变量,初始值为undefined - 发送异步HTTP请求(
login.send()),请求在后台执行,不会阻塞后续代码 - 立刻执行
return res,此时请求还未完成,onreadystatechange的回调函数完全没触发,res仍保持初始的undefined - 等请求完成后,回调里才会给
res赋值,但这时函数早已返回,赋值操作对之前的返回结果没有任何影响
解决方法
方法1:用Promise封装异步操作
将getLogin改成返回Promise的形式,通过async/await或.then()处理异步结果:
function getLogin(){ return new Promise((resolve, reject) => { var login = new XMLHttpRequest(); login.open('POST', 'assets/php/get_player.php', true); login.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); login.onreadystatechange = function() { if (login.readyState == 4) { if(login.status == 200) { resolve(login.responseText); // 请求成功时返回结果 } else { reject(new Error('请求失败')); // 请求失败时抛出错误 } } } login.send(); }) } // 调用时使用async/await处理异步逻辑 startbtn.forEach((button) => { button.addEventListener('click', async (e) => { try { const loginResult = await getLogin(); if (loginResult == "true"){ // 登录成功后的业务逻辑 }else{ alert("Вы не вошли в свой аккаунт!"); } } catch (err) { console.error('请求出错:', err); alert('请求失败,请稍后重试'); } }) });
方法2:使用回调函数
如果不想用Promise,可给getLogin传入回调函数,在请求完成后执行:
function getLogin(callback){ var login = new XMLHttpRequest(); login.open('POST', 'assets/php/get_player.php', true); login.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); login.onreadystatechange = function() { if (login.readyState == 4) { if(login.status == 200) { callback(null, login.responseText); // 成功时传递结果 } else { callback(new Error('请求失败'), null); // 失败时传递错误 } } } login.send(); } // 调用时传入回调处理结果 startbtn.forEach((button) => { button.addEventListener('click', (e) => { getLogin((err, loginResult) => { if (err) { console.error('请求出错:', err); alert('请求失败,请稍后重试'); return; } if (loginResult == "true"){ // 登录成功后的业务逻辑 }else{ alert("Вы не вошли в свой аккаунт!"); } }); }) });
方法3:使用现代的fetch API
XMLHttpRequest属于较旧的API,现代浏览器更推荐使用fetch,写法更简洁:
async function getLogin(){ try { const response = await fetch('assets/php/get_player.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); if (!response.ok) { throw new Error('请求失败'); } return await response.text(); } catch (err) { throw err; } } // 调用方式与Promise版本一致 startbtn.forEach((button) => { button.addEventListener('click', async (e) => { try { const loginResult = await getLogin(); if (loginResult == "true"){ // 登录成功后的业务逻辑 }else{ alert("Вы не вошли в свой аккаунт!"); } } catch (err) { console.error('请求出错:', err); alert('请求失败,请稍后重试'); } }) });
内容的提问来源于stack exchange,提问作者Poshlik
相关产品推荐
相关产品推荐

