如何使用setTimeout限制获取请求中的时间?

时间:2018-11-17 09:46:01

标签: javascript reactjs

我正在开发一个React游戏搜索应用程序,该应用程序从第三方来源提取API数据。当用户搜索找不到的输入时,抓取仅挂在那里而不会停止。基本上,我坚持要弄清楚如何取消获取请求(如果在说10秒后完成一次setTimeout)。如果没有收到响应,那么我希望将其取消并显示错误消息。感谢您的提前帮助!

class Search extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: "",
      games: [],
      error: false,
      loading: false
    }
  }

  updateInput = (event) => {
    this.setState({
      title: event.target.value
    });
  }

  handleGames = (search) => {
    const proxyUrl = `https://cors-anywhere.herokuapp.com/`;
    const key = `8cd10a7136710c1003c8e216d85941ace5a1f00e`;
    const endpoint = `https://www.giantbomb.com/api/search/?api_key=`;
    const url = `${proxyUrl}${endpoint}${key}&format=json&resources=game&query=${search}&limit=30`;

    this.setState({ loading: true }, () => {

      fetch(url)
        .then(res => res.json())
        .then(data => {
          const response = data.results;

          response.forEach(game => {
            this.setState(prevState => ({
              games: prevState.games.concat(game),
              loading: false
            }))
          });
        }).catch(error => {
          console.log('Request failed', error);
        });

      this.setState({
        games: []
      })
    })

  }

  handleSubmit = (e) => {
    const { title } = this.state;
    e.preventDefault();

    if (!title) {
      this.setState({ error: true })
    } else {
      this.setState({ error: false })
      this.handleGames(title);
    }
  }

  render() {
    const { games, error, loading } = this.state;
    return (
      <div className="App">
        <div className="search-bar">
          <form>
            <input
              className="input-field"
              type="text"
              placeholder="Search Game"
              onChange={this.updateInput}
            />
            <button
              className="search-button"
              onClick={this.handleSubmit}
            >Search</button>
          </form>
          <span className="error">{error ? "You kind of need to type something first, genius." : ""}</span>
        </div>
        <div className="games-container">
          {loading ? (
            <div className="loading-div">
              <i className="fa fa-3x fa-spinner fa-spin" />
              <p className="loading">Loading....</p>
            </div>
          ) : (
              games.map(game => {
                return <Game
                  key={game.id}
                  game={game}
                  icon={game.image.icon_url}
                  gameTitle={game.name}
                />
              })
            )

          }
        </div>
      </div>

    );
  }
}

1 个答案:

答案 0 :(得分:0)

您可以将其嵌套在Promise中,而不是直接使用访存。您会发现很多实现都在进行搜索。那是我用过的。

const advFetch = (url, ...) => {
  const TIMEOUT = 10000;
  let didTimeOut = false;

  return new Promise(function(resolve, reject) {
    const timeout = setTimeout(() => {
      didTimeOut = true;
      reject(new Error('Request timed out'));
    }, TIMEOUT);

    fetch(url, ...).then(function(response) {
      clearTimeout(timeout);
      if (!didTimeOut) {
        resolve(response);
      }
    })
    .catch(function(err) {
      if (didTimeOut) {
        return;
      }
      reject(err);
    });
  })
}

注意:获取并没有真正取消(这是不可能的),它将继续直到达到网络超时为止,但是您的应用程序将忽略它。