【问题标题】:Rapid clicking creates too many requests快速点击会产生过多的请求
【发布时间】:2017-09-07 09:19:49
【问题描述】:

我正在使用 react 和 pokeAPI 做一个有趣的小项目(一个 pokedex)。

在应用程序中,用户可以单击口袋妖怪,应用程序将获取该口袋妖怪并在模式框中显示附加信息。

问题是这样的:在模态框中,我已经制作了左右箭头来更改上一个和下一个口袋妖怪,如果用户快速点击其中一个箭头,则每次都会调用 api当点击停止时,用户必须等待之前的所有承诺解决。

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

这里是获取口袋妖怪的方法:

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,
  });
}

}

项目的repo是here

希望大家帮忙!

【问题讨论】:

  • 你研究过去抖吗?
  • 您可以避免在加载时发出新请求,但要跟踪他们请求的口袋妖怪。如果服务器响应返回的不是他们请求的最新宠物小精灵,则发出最新请求。
  • this might be nice,允许你在你的类方法上扔一个小装饰器,虽然我自己没有尝试过
  • 尝试可取消的承诺。 bluebirdjs.com/docs/api/cancellation.html
  • @IrkenInvader 听起来像是一个简单的解决方案。我要试试,谢谢。

标签: javascript reactjs promise fetch-api


【解决方案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);

【讨论】:

    【解决方案2】:

    除了@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);
    

    【讨论】:

      猜你喜欢
      • 2015-10-30
      • 2018-10-26
      • 2020-07-01
      • 1970-01-01
      • 2012-04-17
      • 2020-03-27
      • 1970-01-01
      • 2019-10-13
      • 1970-01-01
      相关资源
      最近更新 更多