调用getLinks函数返回undefined?XMLHttpRequest异步问题解惑
问题原因分析
这是因为你踩了异步请求的典型坑——你用的XMLHttpRequest是异步执行的,具体逻辑如下:
- 你调用
request.open('GET', url, true)时,第三个参数true开启了异步模式,这意味着浏览器发送请求后,不会傻等请求完成,而是直接继续执行后续代码。 - 当
getDeals里调用getLinks('deals_feed')时,getLinks会依次完成:创建请求对象、绑定onload回调、发送请求,然后直接结束函数执行——因为异步请求不会阻塞代码,所以getLinks没有返回任何值,默认就是undefined。 - 你在
request.onload回调里写的return obj,这个return属于回调函数本身,和getLinks的返回值完全没关系。等请求成功、回调函数执行的时候,getDeals里的console.log(url)早就跑完了。
解决办法
针对这个问题,有几种常见的处理方式,优先推荐前两种:
1. 使用回调函数
修改getLinks,让它接受一个回调参数,在请求完成后把结果传给回调:
function getLinks(param, callback) { let url = 'http://localhost/site/feed.php?url=' + param; let request = new XMLHttpRequest(); request.responseType = 'text'; request.onload = function(event) { let obj = request.responseText; console.log(obj); console.log(typeof obj); callback(obj); // 将结果传递给回调函数 }; request.open('GET', url, true); request.send(); } function getDeals() { getLinks('deals_feed', function(resultUrl) { console.log(resultUrl); // 这里就能拿到正确的结果了 }); } getDeals();
2. 使用Promise封装(推荐)
把异步请求包装成Promise,用更清晰的.then()或者async/await语法处理结果:
function getLinks(param) { return new Promise((resolve, reject) => { let url = 'http://localhost/site/feed.php?url=' + param; let request = new XMLHttpRequest(); request.responseType = 'text'; request.onload = function() { let obj = request.responseText; console.log(obj); console.log(typeof obj); resolve(obj); // 请求成功时返回结果 }; request.onerror = function() { reject(new Error('请求失败,请检查网络或地址')); // 处理请求失败的情况 }; request.open('GET', url, true); request.send(); }); } // 方式一:用.then()处理 function getDeals() { getLinks('deals_feed') .then(resultUrl => { console.log(resultUrl); }) .catch(err => { console.error(err); }); } // 方式二:用async/await(更简洁) async function getDeals() { try { let resultUrl = await getLinks('deals_feed'); console.log(resultUrl); } catch (err) { console.error(err); } } getDeals();
3. 改为同步请求(不推荐)
把open方法的第三个参数改成false,强制请求同步执行,但这种方式会阻塞浏览器主线程,导致页面卡顿,只适合临时测试:
function getLinks(param) { let url = 'http://localhost/site/feed.php?url=' + param; let request = new XMLHttpRequest(); request.responseType = 'text'; request.open('GET', url, false); // 开启同步模式 request.send(); let obj = request.responseText; console.log(obj); console.log(typeof obj); return obj; } function getDeals() { let url = getLinks('deals_feed'); console.log(url); // 现在能拿到正确结果 } getDeals();
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

