如何等待XHR请求完成后再执行后续代码?
问题原因
代码运行逻辑和你预期不符是XHR异步执行机制导致的:你把asynchronous参数设为true,inscrit.send()执行后不会等待请求响应返回,会直接执行后续的return people语句,此时onload回调还未触发,people变量还没有赋值。
解决方案1:回调函数实现
把需要用到people的逻辑放到回调函数里,等请求成功后触发执行:
function getInscrits(callback) { let inscrit = new XMLHttpRequest(); let methode = "GET"; let url = "php/getInscrit.php"; let asynchronous = true; inscrit.open(methode, url, asynchronous); inscrit.timeout = 4000; inscrit.onload = function () { if (this.readyState == 4 && this.status == 200) { const people = JSON.parse(this.responseText); // 请求成功后把结果传给回调函数执行 callback(people); } }; inscrit.send(null); } // 调用示例:把要处理报名人员的逻辑写到回调函数里 getInscrits(function(people) { // 这里写后续使用people的代码 console.log(people); renderPeopleList(people); });
解决方案2:Promise封装(推荐)
用Promise包装XHR请求,可以搭配async/await实现类同步逻辑,可读性更高:
function getInscrits() { return new Promise((resolve, reject) => { let inscrit = new XMLHttpRequest(); let methode = "GET"; let url = "php/getInscrit.php"; inscrit.open(methode, url, true); inscrit.timeout = 4000; inscrit.onload = function () { if (this.readyState == 4 && this.status == 200) { const people = JSON.parse(this.responseText); resolve(people); } else { reject(new Error('请求失败')); } }; inscrit.onerror = () => reject(new Error('网络错误')); inscrit.ontimeout = () => reject(new Error('请求超时')); inscrit.send(null); }) } // 调用示例,必须在async函数里使用await async function main() { try { const people = await getInscrits(); // 这里写后续使用people的代码 console.log(people); } catch (err) { // 处理错误 console.error(err.message); } } main();
解决方案3:Fetch API实现
如果项目不需要兼容极低版本浏览器,直接用原生Fetch API更简洁,默认返回Promise:
async function getInscrits() { try { const res = await fetch('php/getInscrit.php', { method: 'GET', signal: AbortSignal.timeout(4000) // 实现4秒超时 }); if (!res.ok) throw new Error('请求失败'); const people = await res.json(); // 后续使用people的逻辑 console.log(people); return people; } catch (err) { console.error(err.message); } }
内容的提问来源于stack exchange,提问作者PascheK7
相关产品推荐
相关产品推荐

