为何jQuery.getJson在循环结束后才执行?如何实现同步?
解决异步请求与循环不同步的问题
问题核心在于jQuery.getJSON是异步操作,它不会阻塞循环执行——循环会一次性跑完151次poke_parser调用,先把所有before日志输出,等所有异步请求陆续完成后,才会触发回调函数输出after日志。
如果需要让请求按顺序执行(或保证后续能基于完整数据排序),可以用以下两种方案:
方案1:按顺序逐个请求(async/await)
把poke_parser改成返回Promise的函数,再用async函数包裹循环,通过await让每个请求完成后再执行下一次循环,确保请求和处理的顺序:
let counter = 151; // 用async函数包裹循环逻辑 async function fetchPokemonSequentially() { const pokemonList = []; for(let i = 1; i <= counter; i++){ let url = `https://pokeapi.co/api/v2/pokemon/${i}`; const data = await poke_parser(url); pokemonList.push(data); } // 所有数据收集完成后排序 pokemonList.sort((a, b) => { // 按需求写排序规则,示例为按ID升序 return a.id - b.id; }); console.log("排序后的列表:", pokemonList); } // 修改poke_parser,返回Promise function poke_parser(url){ console.log("请求中:" + url); return new Promise((resolve, reject) => { jQuery.getJSON(url, function(data){ console.log("请求完成:" + url); resolve(data); // 将请求数据传递出去 }).fail(function(err) { reject(err); // 处理请求失败 }); }); } // 执行函数 fetchPokemonSequentially();
方案2:并行请求后统一排序(效率更高)
如果不需要严格按顺序请求,只是需要最终数据排序,推荐用Promise.all并行发起所有请求,等全部请求完成后再统一排序,速度更快:
let counter = 151; const pokemonPromises = []; // 先收集所有请求的Promise for(let i = 1; i <= counter; i++){ let url = `https://pokeapi.co/api/v2/pokemon/${i}`; pokemonPromises.push(poke_parser(url)); } // 等所有请求完成后处理数据 Promise.all(pokemonPromises) .then(pokemonList => { // 排序 pokemonList.sort((a, b) => a.id - b.id); console.log("排序后的列表:", pokemonList); }) .catch(err => { console.error("请求出错:", err); }); // 修改poke_parser返回Promise function poke_parser(url){ console.log("请求中:" + url); return new Promise((resolve, reject) => { jQuery.getJSON(url, function(data){ console.log("请求完成:" + url); resolve(data); }).fail(function(err) { reject(err); }); }); }
关键说明
- 异步操作的本质是不阻塞后续代码,所以直接在循环里调用异步函数会出现循环先跑完的情况;
- Promise和async/await可以把异步逻辑转换成“看起来同步”的写法,方便控制执行顺序;
- 排序必须等所有数据都获取完成后再执行,否则数据不全无法得到正确结果。
内容的提问来源于stack exchange,提问作者christofer i
相关产品推荐
相关产品推荐

