It’s very clear I don’t understand how functions are scoped in Javascript. Here’s the latest example:
function riseData() {
var jsonResult;
$.ajax({
success: function(data, textStatus, jqXHR){
jsonResult = jqXHR.responseText;
alert("Inside: " + jsonResult);
},
error: function (jqXHR, textStatus, errorThrown) {
$('#errLog').append('<br>Status: ' + qXHR.statusText);
}
});
return jsonResult;
}
$(document).ready(function(){
var intervalID = setInterval('UTCclock()',100);
alert("Outside: " + riseData());
});
When I execute this, the “Inside” alert functions properly, but the “Outside” alert displays “undefined”, even though riseData() is obviously defined only a few lines earlier. There is a $.ajaxSetup earlier in the code which defines the parameters for the ajax call. The ajax call successfully returns the requested data in the “Inside” alert.
I just haven’t the slightest clue how to make the necessary data (jqXHR.responseText) available to other parts of the script.
Can anyone point me at a “Javascript Scoping for Dummies” how-to that addresses this issue?
Your example is scoped just fine. Your problem is you don’t understand the implications of how JavaScript is mainly asynchronous.
Let me go through your example to show you.
riseData.riseDatadeclares a variable,jsonResult.riseDatacalls$.ajax, which schedules an AJAX request to be done, but the response will happen later.$.ajaxis usually non-blocking/asynchronous,riseDatacontinues and returnsjsonResult. SincejsonResulthas not been assigned yet because the AJAX request has not completed, the default value ofundefinedis returned.alert("Outside: "+undefined);.An event loop to a few milliseconds later, this happens:
jsonResultis set, butriseDatahas already returned.alertinsideriseDataalerts with the new data, after the document ready handler has already alertedundefined.There are two solutions to this problem. The first solution is simple, but often results in a worse user experience. This solution is to add the
async: falseoption to$.ajax. This makes$.ajaxblock and freeze the browser.The second solution is to adopt an asynchronous style for almost everything. That means making
riseDataaccept a callback and calling it inside the AJAX response handler. Here’s your code transformed with this method: