Search code examples
javascriptxmlhttprequest

onClick, wait for existing XMLhttprequest() to complete


I'm struggling a bit with this challenge...

I need to do three things:

  • onclick of a button/form submit, wait for the next page to finish loading.
  • And then, wait for an existing API/GET request to complete on the page.
  • And then check the results of that API request.

The problem I'm having, is that when I click my button, the next page hasn't even had a chance to finish loading and my API check executes immediately.

I have looked at numerous solutions, async/wait, some suggested not to use setTimeout(). And I still can't seem to overcome the first hurdle, waiting for the page to finish loading and allowing the existing API call to finish.

How can I wait for an existing API call to finish running?

let button = document.getElementById("signin");
button.setAttribute("onClick", "fireTracking()");

function ajax(url) {
    return new Promise(function(resolve, reject) {
      var xhr = new XMLHttpRequest();
      xhr.onload = function() {
        resolve(this.responseText);
      };
      xhr.onerror = reject;
      xhr.open('GET', url);
      xhr.send();
    });
  }
  
function fireTracking() {
    ajax("www.myurl.com/getstatus")
    .then(function(result) {
    // Code depending on result
    console.log(result);
    console.log("fire event...")
  })
  .catch(function() {
    // An error occurred
  });
}

To confuse things, the URL of the page is the same. So essentially, I can't look out for a different URL.

I'm starting to think I might need to use a setTimeout()? IE, wait 1 second and then make a new API call?

Please note, this is code is running on top of an application. I'm using an AB Testing tool, so I'm essentially trying to get this to work, on top of already compiled code.


Solution

  • That button is submitting a form while triggering your fireTracking function.

    So... That submit is refreshing your page and the result of the Ajax request is just lost.

    You have to prevent the normal submit behavior.

    So here is the "minimal change" to do from your code:

    let button = document.getElementById("signin");
    button.setAttribute("onClick", "fireTracking(event)");  // Add the event argument
    
    function ajax(url) {
        return new Promise(function(resolve, reject) {
          var xhr = new XMLHttpRequest();
          xhr.onload = function() {
            resolve(this.responseText);
          };
          xhr.onerror = reject;
          xhr.open('GET', url);
          xhr.send();
        });
      }
      
    function fireTracking(event) {  // Add the event argument
        event.preventDefault()  // Add this
        ajax("www.myurl.com/getstatus")
        .then(function(result) {
        // Code depending on result
        console.log(result);
        console.log("fire event...")
      })
      .catch(function() {
        // An error occurred
      });
    }
    

    But! a good practice would be to set an event handler for that button using .addEventListener(), like @epacarello mentionned.