循环发起GET请求时JSON.stringify失效问题排查
问题根源:异步请求的执行顺序踩坑啦!
你遇到的核心问题完全是异步操作的执行时机搞的鬼!$.get是异步HTTP请求——你的循环会一口气发起所有请求,但这些请求的回调函数得等服务器返回数据后才会触发。而你在循环结束后立刻调用JSON.stringify(eventList),这时候所有$.get的回调还没来得及执行,eventList['event']自然还是空数组,生成的JSON当然就是{"event": []}。
至于你看到控制台里eventList有正确数据,是因为浏览器控制台会动态更新对象引用——当你展开对象查看时,回调已经执行完填充数据了,但JSON.stringify是在回调执行前就运行了,所以拿到的是当时的空数组状态。
解决方案:等所有请求完成再序列化
这里给你两种常用的解决思路,推荐用第一种,代码更直观:
方法1:用async/await让异步代码“同步化”(ES2017+)
把逻辑包在异步函数里,循环时等待每个请求完成再继续:
async function fetchEvents() { const start = 1518; const end = 1522; const eventList = { event: [] }; for (let i = 0; i < (end - start); i++) { // 用await等待请求返回结果 const response = await $.get(`https://www.someaddress.com/events/index.php?view=${start + i}`); const eventRep = $(response).find('h2').text(); const categoryRep = $(response).find('span.center-name').text(); const descriptionRep = $(response).find('div.description.col-md-9').find('p').text(); eventList.event.push({ title: eventRep, category: categoryRep, description: descriptionRep }); } const str = JSON.stringify(eventList, undefined, 4); console.log(eventList); console.log(str); } // 调用这个异步函数 fetchEvents();
方法2:用jQuery的$.when批量等待请求(兼容旧环境)
如果需要支持老浏览器,可以把所有请求的Promise收集起来,等全部完成后再处理:
const start = 1518; const end = 1522; const eventList = { event: [] }; const requestPromises = []; for (let i = 0; i < (end - start); i++) { // 把每个请求的Promise存入数组 const promise = $.get(`https://www.someaddress.com/events/index.php?view=${start + i}`) .done(function(response) { const eventRep = $(response).find('h2').text(); const categoryRep = $(response).find('span.center-name').text(); const descriptionRep = $(response).find('div.description.col-md-9').find('p').text(); eventList.event.push({ title: eventRep, category: categoryRep, description: descriptionRep }); }); requestPromises.push(promise); } // 等待所有请求完成后再序列化 $.when.apply($, requestPromises).done(function() { const str = JSON.stringify(eventList, undefined, 4); console.log(eventList); console.log(str); });
为啥同步循环就没问题?
你的正常示例是纯同步代码,循环里的每一步都会立刻执行并把数据推入数组,循环结束时数组已经填满了,所以JSON.stringify能拿到完整数据。而异步请求的回调是在JavaScript事件循环的下一轮才会执行,这时候你的序列化代码早就跑完了,自然拿不到后续填充的数据。
内容的提问来源于stack exchange,提问作者fraaahzeep
相关产品推荐
相关产品推荐

