Imagine this function:
JavaScript
x
23
23
1
function myMainFunction() {
2
doSomeInitialStuff();
3
// more stuff..
4
var xhr = new XMLHttpRequest();
5
xhr.onreadystatechange = function () {
6
if (xhr.readyState == XMLHttpRequest.DONE) {
7
// Now that we know we received the result, we can do the heavy lifting here
8
if (xhr.status == 200) {
9
console.log("ready 200");
10
let result = JSON.parse(xhr.responseText);
11
doStuff(result);
12
// and much more stuff..
13
} else {
14
console.log("error", xhr.status);
15
return undefined;
16
}
17
}
18
};
19
20
xhr.open("GET", "http://example.com", true);
21
xhr.send(null);
22
}
23
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
JavaScript
1
8
1
function refactoredMyMainFunction() {
2
doSomeInitialStuff();
3
// more stuff..
4
let result = xhrFunction();
5
doStuff(result); // result would be undefined here, since I cannot wait for the xhr request to finish.
6
7
}
8
Advertisement
Answer
You can implement a callback-based API:
JavaScript
1
27
27
1
function myMainFunction() {
2
doSomeInitialStuff();
3
// more stuff..
4
xhrFunction(doStuff);
5
}
6
7
function xhrFunction(cb) {
8
var xhr = new XMLHttpRequest();
9
xhr.onreadystatechange = function () {
10
if (xhr.readyState == XMLHttpRequest.DONE) {
11
// Now that we know we received the result, we can do the heavy lifting here
12
if (xhr.status == 200) {
13
console.log("ready 200");
14
let result = JSON.parse(xhr.responseText);
15
cb(result);
16
// and much more stuff..
17
} else {
18
console.log("error", xhr.status);
19
return undefined;
20
}
21
}
22
};
23
24
xhr.open("GET", "http://example.com", true);
25
xhr.send(null);
26
}
27