Reputation: 2210
I have the following JavaScript pattern. I'm trying to run "getDataTwo" to run only after "getDataOne" has completely finished. And this means that the XMLHttpRequest has to have returned all data. I've been looking around and I've found info. on callbacks and timeouts and promises. And I've not understood the answer or the explanation did not fit with my particular code pattern (and I could not understand the answer).
When I do: getDataOne(getDataTwo());
I get inconsistent results with the above, because the XMLHttpRequest has not yet kicked off before the next one starts. And so each try to work over the top of each other - more or less.
And when I try something like this: this.getDataOne( function() { this.getDataTwo(); }); which is a feeble attempt at callback (I think), only one function tends to run.
So - my question - how can I reliably have 'getDataTwo' run only when the entire 'processRequest' has completed from the 'getDataOne' call?
Please note, I'd prefer not to use a timer style of function (eg. only run after 3 seconds). Because, who's to say how long that particular piece of string is.
Here's the code pattern:
this.getDataOne = function() {
myURL = this.returnURL();
var xrRW = new XMLHttpRequest();
this.processRequest(apiGSS, xrRW, myURL);
} // end: getDataOne
this.getDataTwo = function() {
myURL = this.returnURL();
var xrRW = new XMLHttpRequest();
this.processRequest(apiGSS, xrRW, myURL);
} // end: getDataTwo()
this.processRequest = function(iAPI, xReq, strCommand) {
xReq.onreadystatechange = function() {
if (xReq.readyState === 4) {
if (xReq.status === 200) {
// parse JSON data...
Do JSON work here
// write parsed data to screen...
// by calling a function and sending it the parsed JSON data
writeToScreen(arrayofJSONData());
} // end: xReq.readyState === 200
} // end: xReq.readyState === 4
} // end: onreadystatechange
xReq.open("GET", strCommand, true);
xReq.send(null);
} // end: processRequest
Upvotes: 1
Views: 213
Reputation: 2210
It turns out my code was wonky. Here's the fix for my situation (thanks to people who answered, turns out I didn't share quite enough information to help you understand my full situation).
I am now using this calling pattern successfully: "getDataOne(getDataTwo());" (without the quotes). What I am doing differently in the 'getDataOne' and 'getDataTwo' functions is that I'm not setting variables within a single array (not shown in my original code, sorry). So when getDataOne was being called it was writing to the same array that getDataTwo was relying on, and further, returnURL and processRequest were checking that same single array for logic on what they each had to do. Since the 'last one to update the array won', the overall code would fail. Here's a better share of what my code is now doing, and doing well, now that it is not trying to read a single array that was being contested over by competing functions (yay):
getDataOne(getDataTwo());
this.getDataOne = function() {
myURL = this.returnURL("byOne type", "byOne query");
this.processRequest(apiGSS, xrRW, myURL, "byOne Type");
} // end: getDataOne
this.getDataTwo = function() {
myURL = this.returnURL("byTwo type", "byTwo query");
this.processRequest(apiGSS, myURL "byTwo type");
} // end: getDataTwo()
this.returnURL( byType, byQuery ) {
// return a URL that matches the byType and byQuery requirements
}
this.processRequest = function(iAPI, strCommand, byType) {
var xReq = new XMLHttpRequest();
xReq.onreadystatechange = function() {
if (xReq.readyState === 4) {
if (xReq.status === 200) {
if (byType === "byTwo type") {
// do this...
} else {
// do that...
} // end: (byType === "byTwo type" )
} // end: xReq.readyState === 200
} // end: xReq.readyState === 4
} // end: onreadystatechange
xReq.open("GET", strCommand, true);
xReq.send(null);
} // end: processRequest
Upvotes: 1
Reputation: 41958
You're pretty close, you just have to actually pass and invoke the callback:
this.getDataOne = function() {
myURL = this.returnURL();
var xrRW = new XMLHttpRequest();
this.processRequest(apiGSS, xrRW, myURL, this.getDataTwo);
} // end: getDataOne
this.getDataTwo = function() {
myURL = this.returnURL();
var xrRW = new XMLHttpRequest();
this.processRequest(apiGSS, xrRW, myURL);
} // end: getDataTwo()
this.processRequest = function(iAPI, xReq, strCommand, onSuccess) {
xReq.onreadystatechange = function() {
if (xReq.readyState === 4) {
if (xReq.status === 200) {
if(onSuccess) {
onSuccess();
}
} // end: xReq.readyState === 200
} // end: xReq.readyState === 4
} // end: onreadystatechange
xReq.open("GET", strCommand, true);
xReq.send(null);
} // end: processRequest
Of course for further optimization I would recommend moving creating the XHR object to the processRequest
function as well.
Upvotes: 0