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

如何保证HTML字段始终填充最后一次发起的API请求返回的数据?

问题原因

你遇到的是异步请求的竞态条件问题:网络请求的返回顺序不受发起顺序控制,更早发起的请求可能后返回,导致旧数据覆盖了后续新请求应该渲染的结果。

解决方案

这里提供两种实现简单、改造成本低的方案:

方案1:新增标识过滤旧请求(零延迟,实时请求)

只需要新增1个全局变量做校验,不需要修改原有逻辑,就能保证永远只渲染最后一次请求的结果:

const pokemonId = document.getElementById("pokemon-id");
const pokemonName = document.getElementById("pokemon-name");
const pokemonType = document.getElementById("pokemon-type");
const pokemonHeight = document.getElementById("height");
const pokemonWeight = document.getElementById("weight");
const pokemonSearch = document.getElementById("pokemon-search");
// 新增:记录最新的搜索值
let latestSearch = '';

async function fetchPokemon(idOrName) {
    const endpoint = "https://pokeapi.co/api/v2/pokemon/";
    const response = await fetch(endpoint + idOrName);

    if (!response.ok) return null;

    return response.json();
}

function fillPokemonFields(pokemon) {
    if(!pokemon) return;

    pokemonId.textContent = pokemon.id;
    pokemonName.textContent = pokemon.name;
    pokemonType.textContent = pokemon.type;
    pokemonHeight.textContent = pokemon.height;
    pokemonWeight.textContent = pokemon.weight;
}

pokemonSearch.addEventListener("input", async function () {
    let input = this.value.trim();
    // 每次触发输入都更新最新搜索值
    latestSearch = input;
    if (!input) return;

    let pokemon = await fetchPokemon(input);
    // 只有当前请求的输入值等于最新搜索值时,才渲染结果
    if (input === latestSearch) {
        fillPokemonFields(pokemon);
    }
});

方案2:防抖优化(减少请求数,体验更友好)

如果不需要输入实时触发请求,可以加防抖逻辑,用户连续输入时不会频繁发起请求,只会在停止输入固定时长后发起一次请求,从根源上避免多请求并发的竞态问题:

const pokemonId = document.getElementById("pokemon-id");
const pokemonName = document.getElementById("pokemon-name");
const pokemonType = document.getElementById("pokemon-type");
const pokemonHeight = document.getElementById("height");
const pokemonWeight = document.getElementById("weight");
const pokemonSearch = document.getElementById("pokemon-search");

// 防抖工具函数,delay可自行调整,默认300ms
function debounce(func, delay = 300) {
    let timer = null;
    return function(...args) {
        clearTimeout(timer);
        timer = setTimeout(() => func.apply(this, args), delay);
    }
}

async function fetchPokemon(idOrName) {
    const endpoint = "https://pokeapi.co/api/v2/pokemon/";
    const response = await fetch(endpoint + idOrName);

    if (!response.ok) return null;

    return response.json();
}

function fillPokemonFields(pokemon) {
    if(!pokemon) return;

    pokemonId.textContent = pokemon.id;
    pokemonName.textContent = pokemon.name;
    pokemonType.textContent = pokemon.type;
    pokemonHeight.textContent = pokemon.height;
    pokemonWeight.textContent = pokemon.weight;
}

// 用防抖函数包裹原回调逻辑
pokemonSearch.addEventListener("input", debounce(async function () {
    let input = this.value.trim();
    if (!input) return;

    let pokemon = await fetchPokemon(input);
    fillPokemonFields(pokemon);
}));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 09:24:01