如何遍历Star Wars API多页获取星舰数据?代码死循环排查
解决Star Wars API多页数据获取的无限循环问题
兄弟,你的问题出在同步循环和异步操作的冲突上!咱们一点点拆解:
你写的while循环是同步执行的,但fetch是异步请求——也就是说,循环会在fetch的回调(.then里的代码)执行之前,就已经跑了N次,因为它根本不会等请求完成。这就导致next = nextData.next这个赋值永远赶不上循环的节奏,next一直保持初始的非null值,循环根本停不下来,直接把浏览器搞崩溃了。
下面给你两种靠谱的解决方案,选哪种看你习惯:
方案1:用async/await让异步代码“同步化”
这个方案最直观,把异步请求的等待逻辑用await处理,让循环按顺序执行:
async function getData() { let totalResults = []; try { // 先拿第一页数据 let firstResponse = await fetch('https://swapi.co/api/starships/'); let firstPageData = await firstResponse.json(); // 注意用扩展运算符,把星舰对象直接推进数组,而不是推整个数组(避免二维数组) totalResults.push(...firstPageData.results); let nextPageUrl = firstPageData.next; // 循环获取后续页面,每次都等请求完成再走下一轮 while (nextPageUrl !== null) { let response = await fetch(nextPageUrl); let pageData = await response.json(); totalResults.push(...pageData.results); nextPageUrl = pageData.next; } console.log('所有星舰数据已获取:', totalResults); return totalResults; } catch (error) { console.error('获取数据时出错:', error); throw error; } } // 调用函数 getData();
关键要点:
- 用
async标记函数,await会暂停代码执行,直到fetch请求完成并返回结果,这样nextPageUrl会被及时更新 - 用
...pageData.results替代直接推数组,确保totalResults是一维数组(你之前的代码会把每个页面的结果数组作为元素推进去,变成二维数组,大概率不是你想要的) - 加
try/catch处理网络请求可能出现的错误,避免代码直接挂掉
方案2:用递归处理分页请求
如果不想用async/await,递归也是个好办法,让每一页的请求都在前一页完成后再发起:
function getData() { let totalResults = []; // 定义递归函数,负责获取单页数据并处理下一页 function fetchSinglePage(url) { return fetch(url) .then(res => res.json()) .then(pageData => { totalResults.push(...pageData.results); // 如果还有下一页,就递归调用自己 if (pageData.next !== null) { return fetchSinglePage(pageData.next); } else { // 所有页面都获取完了,返回最终结果 return totalResults; } }) .catch(error => { console.error('请求出错:', error); throw error; }); } // 从第一页开始发起请求 return fetchSinglePage('https://swapi.co/api/starships/') .then(allResults => { console.log('全部星舰数据:', allResults); return allResults; }); } // 调用函数 getData();
关键要点:
- 递归函数会在当前页请求完成后,判断是否有下一页,如果有就继续调用自己,直到
next为null - 这种方式天然保证了请求的顺序,不会出现同步循环那种“抢跑”的问题
最后再强调下你的原代码问题
原代码里的while循环是同步的,它根本不会等fetch的.then回调执行,所以next的值永远不会在循环里被更新——循环刚跑起来,就已经发起了无数个fetch请求,浏览器直接被打崩了。上面两种方案都是让异步请求按顺序执行,确保next能被正确更新,自然就不会无限循环了。
内容的提问来源于stack exchange,提问作者Amitk88
相关产品推荐
相关产品推荐

