Search code examples
javascriptdjangoasync-awaitfetchcelery

JavaScript async/await polling to get a status - function doesn't return the correct data


Context: asynchronous tasks management in Django with Celery and Redis.

I have a function that sends a POST request in Ajax. The server returns a task id.

With the task id I launch another function just after the POST request to fetch the task status in order to check if the worker has executed the task successfully.

Problem: I succeed in doing the polling with javascript and log the results. But at the end my function doesn't returns the correct data (the one in the if statement). It's as if the object returned by the if statement is ignored.

It's the first time I write such a function. Any help would be much appreciated 🙏

Code

function cancelSimcard() {
  const cancellationLink = document.getElementById("cancellationLink");

  return {
    notificationOpen: false,
    message: "à remplacer",

    async sendCancellationRequest() {
      const data = await fetch(cancellationLink.dataset.url, {
        method: "POST",
      });
      const result = await data.json();
      const status = await getStatus(result.task_id);
    },
  };

  async function getStatus(task_id) {
    const statusData = await fetch(`/parc/task_status/${task_id}`, {
      method: "GET",
    });
    const statusResult = await statusData.json();

    if (statusResult.task_status === "SUCCESS") {
      console.log("DATA FROM SUCCESS BLOCK", statusResult);
      return statusResult;
    } else {
      await new Promise((resolve) => setTimeout(resolve, 1000));
      await getStatus(statusResult.task_id);
    }
    console.log("DATA AT THE END", statusResult);
  }
}

Console result:

enter image description here

**I'm trying to get the data from the success block to pass it in sendCancellationRequest() function. **


Solution

  • Your getStatus function doesn't return anything when executing the else block, so it returns undefined. In other words, whatever the recursive call of getStatus returns, it is ignored, and undefined is returned instead.

    This kind of polling can be implemented with a loop instead of recursion, which lowers the likelihood of making such a mistake:

      // Define this once for all:
      const delay = ms => new Promise((resolve) => setTimeout(resolve, ms));
    
      async function getStatus(task_id) {
        while (true) { // Loop
          const statusData = await fetch(`/parc/task_status/${task_id}`, {
            method: "GET",
          });
          const statusResult = await statusData.json();
          if (statusResult.task_status === "SUCCESS") {
            console.log("DATA FROM SUCCESS BLOCK", statusResult);
            return statusResult;
          }
          await delay(1000);
        }
      }