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); }