快速点击会产生太多请求

时间:2017-04-11 20:01:28

标签: javascript reactjs promise fetch-api

我正在使用react和pokeAPI进行一个小型的for-fun-project项目(pokedex)。

在应用程序中,用户可以点击宠物小精灵,应用程序将获取该宠物小精灵并在模式框中显示其他信息。

问题在于:在模态框中,我已经将左箭头和右箭头更改为上一个和下一个小宠物,如果用户快速点击其中一个箭头,则每次都会调用api当点击停止时,用户必须等待所有先前的承诺解决。

我不想在加载时禁用方法或按钮,因为它应该可以通过口袋妖怪运行。我基本上只想拒绝先前的承诺,如果新的承诺。这可能吗?

以下是获取宠物小精灵的方法:

showDetails(pokemon){
//check if the pokemon is already is state
const statePokemon = this.state.pokemon.find(p => {
   return p.name === pokemon;
});
if(!statePokemon) {
  //set loading and pass the pokemon as a string
  //to show which pokemon is being fetched
  this.setState({
    pokemonLoading : true,
    pokemonFetched : false,
    showing : pokemon,
  });
  let pokemonArr = [...this.state.pokemon];
  let newPokemon = {};
  fetch(`http://pokeapi.co/api/v2/pokemon/${pokemon}`)
  .then(response => response.json())
  .then(response => {
    pokemonArr.push(response);
    newPokemon = response;
  })
  .then((_) => {
    //don't update state with new pokemon
    //if user has closed modal while loading
    if (this.state.showing) {
      this.setState({
        pokemon : pokemonArr,
        pokemonLoading : false,
        pokemonFetched : true,
        showing : newPokemon,
      });
    }
  });
} else {
  //set showing with pokemon from state
  //without making a new fetch
  this.setState({
    showing : statePokemon,
    pokemonFetched : true,
  });
}

}

该项目的回购是here

希望你们能帮忙!

2 个答案:

答案 0 :(得分:1)

你可以使用去抖功能。这将允许该函数仅在给定的时间段内运行这么多次。

function debounce(fn, wait) {
  let timeout;
  return (...args) => {
    const waitFn = () => {
      timeout = clearTimeout(timeout);
      fn(...args);
    };
    if (!timeout) {
      timeout = setTimeout(waitFn, wait);
    }
  };
}

// this will run the showDetails function only once every 500ms
this.showDetails = debounce(this.showDetails.bind(this), 500);

答案 1 :(得分:0)

除了@ realseanp的回答之外,您还可以尝试限制

function throttle(duration, fn) {
  let inProgress;
  return () => {
    if (inProgress) {
      clearTimeout(inProgress);
    }
    inProgress = setTimeout(fn, duration);
  };
}

window.addEventListener('keydown', throttle(500, () => console.log('keydown')), false);