DJ2
DJ2

Reputation: 1741

React - setTimeout() method not firing after Promise.all

I have an arrow function that is invoked from cDM to retrieve the updated status of schedules every 20 seconds with a setTimeout(). The setTimeout() method never fires another request to the server like it's supposed to. So I'm thinking the code is never reached. I'm not sure exactly how to modify it so the method is reached.

componentDidMount() {
    //get request to /schedules
    //update state with response data
    this.getUpdatedStatus();
}

  getUpdatedStatus = () => {
    //fetch updated status,
    //list of arrays that are updated to state in `cDM`
    const schedules = this.state.schedules;
    Promise.all(
      schedules
        .map(schedule =>
          axios({
            method: "get",
            url: schedule.selfUri,
            headers: {
              Accept: " someValue"
            }
          })
        )
        .then(response => {
          if (response.data.data[0].status !== "Complete") {
            this.timeout = setTimeout(() => this.getUpdatedStatus(), 20000);
          }
          console.log(response);
          this.setState(
            {
              scheduleStatus: response.data.data[0].status,
            },
            () => {
              console.log(this.state.scheduleStatus);
            }
          );
        })
    ).catch(error => console.log(error.response));
  };

Codesandbox

Upvotes: 1

Views: 207

Answers (2)

Niloct
Niloct

Reputation: 10015

Well, basically @PrinceHernandez found the main issue, but there were a lot of other problems with your code:

  • input field was read only
  • missing tbody
  • missing key attribute on each tr

I took the liberty to polish as I could, here: https://codesandbox.io/s/6vyk48x18n

Open console and you will see that the code updates every 2s printing 1. Moving thenable to each schedule made necessary to have a flag controlling ONE invocation of timeout per getUpdatedStatus.

Upvotes: 0

Prince Hernandez
Prince Hernandez

Reputation: 3721

in simple words, you are using wrong the Promise.all(), this is because the structure is something like:

Promise.all([p1, p2,...,pn]).then([r1, r2, ..., rn])

but your code is something like: Promise.all([p1, p2,...,pn].then(r))

so basically your promise.all should be changed to something like this:

  getUpdatedStatus = () => {
    //fetch updated status,
    //list of arrays that are updated to state in `cDM`
    const schedules = this.state.schedules;
    Promise.all(
      schedules
        .map(schedule =>
          axios({
            method: "get",
            url: schedule.selfUri,
            headers: {
              Accept: " someValue"
            }
          })
        ))
        .then(responses => {
          //now you have to iterate over the responses
          const isIncomplete = responses.some(r => r.data.data[0].status !== "Complete")
          if (isIncomplete) {
            this.timeout = setTimeout(() => this.getUpdatedStatus(), 20000);
          }
          console.log(responses);
          this.setState(
            {
              scheduleStatus: isIncomplete?'Pending':'Complete',//improve this piece of code
            },
            () => {
              console.log(this.state.scheduleStatus);
            }
          );
        })
  };

here you have a working sandbox with the code that you provided on your sandbox.

Upvotes: 1

Related Questions