JS调用PokeAPI拉取宝可梦数据后追加DOM顺序错乱如何修复?
问题原因
你循环并发发起的fetch请求是异步的,HTTP响应返回的顺序不受请求顺序控制,编号小的宝可梦请求可能比编号大的更晚返回,后返回的小编号卡片会被appendChild插到对应世代容器的末尾,最终出现顺序错乱。另外Card函数中每次插入卡片都重复执行pagina.appendChild(世代容器)的操作,会反复移动世代容器的位置,也是导致顺序混乱的原因之一。
修复方案
方案1:等待所有请求完成后按顺序统一渲染(逻辑最简单,不易出错)
改写prova函数,用Promise.all按请求顺序收集所有接口返回结果,再遍历生成卡片:
async function prova() { // 按顺序生成所有请求的Promise数组 const fetchTasks = [] for (let id = 1; id < 899; id++) { fetchTasks.push( fetch(`https://pokeapi.co/api/v2/pokemon/${id}/`) .then(response => response.json()) ) } // 所有请求返回后,结果顺序和请求顺序完全一致 const pokemonList = await Promise.all(fetchTasks) // 按编号顺序生成并插入卡片 pokemonList.forEach(data => { const pokemonNumber = data.id const pokemonName = data.name.charAt(0).toUpperCase() + data.name.slice(1) const pokemontypes = data.types.map(item => item.type.name) const pokemontype1 = pokemontypes[0] const pokemontype2 = pokemontypes[1] Card(pokemontype1, pokemontype2, pokemonNumber, pokemonName) }) }
同时删除Card函数中所有pagina.appendChild(pokGenX)的代码,世代容器只需要在页面初始化时插入一次到pagina节点即可,不需要每次加卡片都重复插入。
方案2:占位符预占位(请求返回一个渲染一个,不用等全部加载完)
页面初始化时,先给每个世代容器按该世代的宝可梦编号范围插入对应数量的空占位节点,给每个占位节点设置唯一ID比如placeholder-${编号},请求返回后直接找到对应编号的占位节点,替换成生成的卡片即可,不受响应返回顺序影响。
内容的提问来源于stack exchange,提问作者Andrea Crinella
相关产品推荐
相关产品推荐

