You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PokeAPI制作的宝可梦图鉴列表顺序混乱问题求助

宝可梦图鉴列表顺序混乱问题排查

我用HTML、CSS和JavaScript制作了一个宝可梦图鉴,通过PokeAPI获取数据生成宝可梦列表,但显示时列表顺序混乱,刷新页面后顺序还会发生变化。以下是我的代码及页面情况:

document.addEventListener('DOMContentLoaded', function () {
    const pokemonList = document.querySelector('.pokemon-list');
    const pokemonDetails = document.querySelector('.pokemon-details');

    function fetchPokemonDetails(id) {
        fetch(`https://pokeapi.co/api/v2/pokemon/${id}`)
            .then(response => response.json())
            .then(data => displayPokemonDetails(data));
    }

    function displayPokemonDetails(pokemon) {
        pokemonDetails.innerHTML = `
            <h2>${pokemon.name}</h2>
            <img src="${pokemon.sprites.front_default}" alt="${pokemon.name}">
            <p>Height: ${pokemon.height} dm</p>
            <p>Weight: ${pokemon.weight} hg</p>
        `;

        pokemonDetails.style.display = 'block';
    }


    function displayPokemon(pokemon) {
        const pokemonCard = document.createElement('div');
        pokemonCard.classList.add('pokemon');
        pokemonCard.dataset.id = pokemon.id;

        pokemonCard.innerHTML = `
            <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png" alt="${pokemon.name}">
            <p>${pokemon.name}</p>
        `;

        pokemonCard.addEventListener('click', function () {
            const id = this.dataset.id;
            fetchPokemonDetails(id);
        });

        pokemonList.appendChild(pokemonCard);
    }


    for (let i = 1; i <= 1016; i++) {
        fetch(`https://pokeapi.co/api/v2/pokemon/${i}`)
            .then(response => response.json())
            .then(data => displayPokemon(data));
    }

    pokemonList.sort((a, b) => a.id - b.id);

});
  • 列表初始显示状态:列表预览
  • 刷新后显示状态:刷新后预览

问题原因

  1. 异步请求的无序性:循环中发起的1016个fetch请求是异步的,API响应返回时间不固定,哪个请求先拿到数据就先渲染对应的宝可梦卡片,导致列表顺序混乱,且每次刷新的响应顺序不同,列表也随之变化。
  2. 无效的排序操作:最后一行的pokemonList.sort(...)完全无效——pokemonList是DOM容器元素,本身没有sort方法;而且这行代码在请求发起后立刻执行,此时所有请求都未返回,DOM中还没有宝可梦卡片,根本无法排序。

解决方案

方案1:批量获取数据后排序渲染(推荐)

先收集所有请求的Promise,用Promise.all等待所有数据返回,按ID排序后再统一渲染,保证顺序正确:

document.addEventListener('DOMContentLoaded', function () {
    const pokemonList = document.querySelector('.pokemon-list');
    const pokemonDetails = document.querySelector('.pokemon-details');

    function fetchPokemonDetails(id) {
        fetch(`https://pokeapi.co/api/v2/pokemon/${id}`)
            .then(response => response.json())
            .then(data => displayPokemonDetails(data));
    }

    function displayPokemonDetails(pokemon) {
        pokemonDetails.innerHTML = `
            <h2>${pokemon.name}</h2>
            <img src="${pokemon.sprites.front_default}" alt="${pokemon.name}">
            <p>Height: ${pokemon.height} dm</p>
            <p>Weight: ${pokemon.weight} hg</p>
        `;
        pokemonDetails.style.display = 'block';
    }

    function displayPokemon(pokemon) {
        const pokemonCard = document.createElement('div');
        pokemonCard.classList.add('pokemon');
        pokemonCard.dataset.id = pokemon.id;

        pokemonCard.innerHTML = `
            <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png" alt="${pokemon.name}">
            <p>${pokemon.name}</p>
        `;

        pokemonCard.addEventListener('click', function () {
            const id = this.dataset.id;
            fetchPokemonDetails(id);
        });

        pokemonList.appendChild(pokemonCard);
    }

    // 收集所有请求的Promise
    const pokemonPromises = [];
    for (let i = 1; i <= 1016; i++) {
        pokemonPromises.push(fetch(`https://pokeapi.co/api/v2/pokemon/${i}`).then(res => res.json()));
    }

    // 等待所有数据返回后排序渲染
    Promise.all(pokemonPromises)
        .then(pokemons => {
            pokemons.sort((a, b) => a.id - b.id);
            pokemons.forEach(pokemon => displayPokemon(pokemon));
        })
        .catch(err => console.error('数据获取失败:', err));
});

方案2:按顺序发起请求

用async/await逐个发起请求,保证请求和渲染的顺序与ID一致(适合小批量数据,大批量可能耗时较长):

document.addEventListener('DOMContentLoaded', async function () {
    const pokemonList = document.querySelector('.pokemon-list');
    const pokemonDetails = document.querySelector('.pokemon-details');

    function fetchPokemonDetails(id) {
        fetch(`https://pokeapi.co/api/v2/pokemon/${id}`)
            .then(response => response.json())
            .then(data => displayPokemonDetails(data));
    }

    function displayPokemonDetails(pokemon) {
        pokemonDetails.innerHTML = `
            <h2>${pokemon.name}</h2>
            <img src="${pokemon.sprites.front_default}" alt="${pokemon.name}">
            <p>Height: ${pokemon.height} dm</p>
            <p>Weight: ${pokemon.weight} hg</p>
        `;
        pokemonDetails.style.display = 'block';
    }

    function displayPokemon(pokemon) {
        const pokemonCard = document.createElement('div');
        pokemonCard.classList.add('pokemon');
        pokemonCard.dataset.id = pokemon.id;

        pokemonCard.innerHTML = `
            <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png" alt="${pokemon.name}">
            <p>${pokemon.name}</p>
        `;

        pokemonCard.addEventListener('click', function () {
            const id = this.dataset.id;
            fetchPokemonDetails(id);
        });

        pokemonList.appendChild(pokemonCard);
    }

    // 按顺序逐个请求并渲染
    try {
        for (let i = 1; i <= 1016; i++) {
            const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${i}`);
            const data = await response.json();
            displayPokemon(data);
        }
    } catch (err) {
        console.error('数据获取失败:', err);
    }
});

补充建议

  • 方案1一次性发起大量请求可能触发API限流,建议分批次请求(比如每次请求20个,完成后再请求下一批)。
  • 可以使用PokeAPI的列表接口https://pokeapi.co/api/v2/pokemon?limit=1016先获取所有宝可梦的基础信息(含ID和详情URL),再批量请求详情,更规范且能避免手动循环ID的潜在问题。

内容的提问来源于stack exchange,提问作者KAIJUU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 01:42:41