Search code examples
javascriptreactjsfetch-apiaudio-player

Block request if the previous request is still incomplete


I'm fetching songs from API, everything is working fine but when the user clicks a song to play and then presses another one before the first song is played the two audios run together, so I'm trying to find a way to block the user from making requests until the previous request is done here is the code:

const handlePlay = (id) => {
    //console.log(id);

    if (id === now) {
      setNow("");
    } else {
      setNow(id);
    }
    audio && audio.pause();
    fetch(`https://spotify23.p.rapidapi.com/tracks/?ids=${id}`, options)
      .then((response) => response.json())
      .then((response) => {
        setPlaynig(response.tracks);
        return response.tracks[0].preview_url;
      })
      .then((response) => {
        if (id !== now) {
          setAudio(new Audio(response));
        }
      })
      .catch((err) => console.error(err));
  };

I tried attaching a .then that sets the pending state to false when the audio is set but it still gave the same error


Solution

  • I think if you use the pending state but apply that immediately upon entering the function and remove it before you setAudio again, that should work. I'm assuming the problem is the requests are made concurrently before one has a chance to enter the .then clause. So doing this ensures that you block any requests if one has initiated, until the request is final.

    const handlePlay = (id) => {
    //console.log(id);
    if(pending) return;
    setPending(true)
    if (id === now) {
      setNow("");
    } else {
      setNow(id);
    }
    audio && audio.pause();
    fetch(`https://spotify23.p.rapidapi.com/tracks/?ids=${id}`, options)
      .then((response) => response.json())
      .then((response) => {
        setPlaynig(response.tracks);
        return response.tracks[0].preview_url;
      })
      .then((response) => {
        if (id !== now) {
          setAudio(new Audio(response));
          setPending(false);
        }
      })
      .catch((err) => {
       setPending(false);
       console.error(err));
      }
    

    };