如何确保XMLHttpRequest完成响应后再返回完整结果数组?
解决XMLHttpRequest循环请求后无法返回完整响应数组的问题
原代码的核心问题是未将每个XMLHttpRequest请求包装为Promise,同时错误使用await和map,导致异步请求还未完成就提前返回空数组。具体问题点:
map是同步方法,await无法等待其内部的异步请求执行完毕onreadystatechange会触发多次,未正确判断请求是否完成- 未将单个请求转化为Promise,无法通过
Promise.all统一等待所有请求结束
修复方案
1. 封装单个XHR请求为Promise
先把单个XMLHttpRequest请求包装成Promise,明确处理成功和失败的情况:
// 封装XHR请求为Promise,确保请求完成后才返回结果 function fetchWithXHR(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'json'; // 请求成功完成时触发 xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { resolve(xhr.response); } else { reject(new Error(`请求失败,状态码:${xhr.status}`)); } }; // 网络错误时触发 xhr.onerror = () => { reject(new Error('网络请求出错')); }; xhr.send(); }); }
2. 重构请求函数
利用Promise.all等待所有请求完成,返回完整的响应数组:
const getFetched = async () => { const requestURLArray = await getURLArray(); // 把每个URL转为Promise,用Promise.all等待全部完成 return Promise.all(requestURLArray.map(url => fetchWithXHR(url))); };
3. 正确调用函数
使用async/await或.then()获取最终结果:
// 方式1:用.then()调用 getFetched().then(fetchedData => { console.log(fetchedData.length); // 现在会正确显示响应数量 console.log(fetchedData); // 完整的响应数组 }).catch(error => { console.error('请求出错:', error); }); // 方式2:用async/await调用 async function main() { try { const fetchedData = await getFetched(); console.log(fetchedData.length); console.log(fetchedData); } catch (error) { console.error('请求出错:', error); } } main();
修复逻辑说明
- 每个XHR请求被包装为Promise后,只有当请求成功完成(
onload且状态码正常)才会resolve,出错则reject requestURLArray.map生成Promise数组,Promise.all会等待所有Promise都resolve后,返回按顺序排列的完整响应数组- 去掉冗余的嵌套调用,用
async/await让代码逻辑更清晰
内容的提问来源于stack exchange,提问作者Joe Moore
相关产品推荐
相关产品推荐

