Skip to content
Advertisement

How to separate XMLHttpRequest from the main function for better visbility/testibility (without Promises / asnyc/await )

Imagine this function:

function myMainFunction() {
  doSomeInitialStuff();
  // more stuff..
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (xhr.readyState == XMLHttpRequest.DONE) {
      // Now that we know we received the result, we can do the heavy lifting here
      if (xhr.status == 200) {
        console.log("ready 200");
        let result = JSON.parse(xhr.responseText);
        doStuff(result);
        // and much more stuff..
      } else {
        console.log("error", xhr.status);
        return undefined;
      }
    }
  };

  xhr.open("GET", "http://example.com", true);
  xhr.send(null);
}

This works fine, but it is impossible to test, and this function has become a monster. So I’d like to refactor it, by separating all the different parts in their own unique functions.
The problem is, I do not know how to extract the XHR part and still keep it working.
I cannot use Promises nor asnyc/await and have to stick to using plain XHR.
What I’d normally do is to create a seperate async function for the ajax call (or the xhr in this case). Simply await it’s result and go from there. Easy to separate. But I do not have the luxury of await or anything this time.

What I am trying to get at is something like this

function refactoredMyMainFunction() {
  doSomeInitialStuff();
  // more stuff..
  let result = xhrFunction(); 
  doStuff(result); // result would be undefined here, since I cannot wait for the xhr request to finish. 

}

Advertisement

Answer

You can implement a callback-based API:

function myMainFunction() {
  doSomeInitialStuff();
  // more stuff..
  xhrFunction(doStuff);
}

function xhrFunction(cb) { 
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (xhr.readyState == XMLHttpRequest.DONE) {
      // Now that we know we received the result, we can do the heavy lifting here
      if (xhr.status == 200) {
        console.log("ready 200");
        let result = JSON.parse(xhr.responseText);
        cb(result);
        // and much more stuff..
      } else {
        console.log("error", xhr.status);
        return undefined;
      }
    }
  };

  xhr.open("GET", "http://example.com", true);
  xhr.send(null);
}
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement