My code sends requests to Twitter for search data gets responses in the from of JSON. After getting the JSON, it stores the count of responses that match a certain condition in an array.
Here is the code that makes the call to the function that queries Twitter.
$(document).ready(function() {
...
graph = new HighCharts.chart({
chart: {
events: {
load: function() {
console.log("events.load");
var that = this;
var update = function() {
if (polling) {
console.log("update()");
// The least index series will be nearest the x-axis
var stackNumber = 0;
var numTweets = updateValues();
console.log(numTweets + "");
for (var i = 0, currentSeries = that.series; i < currentSeries.length; i++) {
var x = (new Date()).getTime(), // current time
y = numTweets[i];
stackNumber += y;
currentSeries[i].addPoint([x, y], true, true);
}
}
}
// set up the updating of the chart each second
var series = this.series[0];
setInterval(update, 1000);
}
}
(I’m probably missing some brace somewhere in the code-paste here, but I know for sure that my problem isn’t related to a missing brace)
And here is the function that actually queries Twitter using a series of jQuery calls. The updateValues() function (which is outside the document-ready section) goes as follows:
function updateValues() {
var url = "http://search.twitter.com/search.json?callback=?&q=";
var cls = "Penn_CIS240"
var query = "%23" + cls;
var voteCount = [0,0,0,0];
// create an array of zeros
//for (var i = 0; i < 4; i++)
// voteCount.push(0);
$.getJSON(url + query, function(json){
console.log(json);
$.each(json.results, function(i, tweet) {
var user = tweet.from_user_id;
if (user % 2 == 0) {
voteCount[0] += 1;
}
else if (user % 3 == 0) {
voteCount[1] += 1;
}
else if (user % 5 == 0) {
voteCount[2] += 1;
}
else {
voteCount[3] += 1;
}
console.log("updateValues() -> getJSON -> each -> voteCount = " + voteCount);
});
console.log("updateValues() -> getJSON -> voteCount = " + voteCount);
});
console.log("updateValues() -> voteCount = " + voteCount);
return voteCount;
}
What is happening is that the variable voteCount is getting incremented properly inside the jQuery calls. However, outside of the calls, it is getting reset. So the log outputs look something like this:
updateValues() -> getJSON -> each -> voteCount = [1,0,0,0]
updateValues() -> getJSON -> voteCount = [1,0,0,0]
updateValues() -> voteCount = [0,0,0,0]
Does this problem have to do with jQuery’s asynchronous calls, and I’m having interesting variable modification conflicts? Or is it something else?
When you use asynchronous callbacks in JavaScript, they execute later… asynchronously. So if you have:
the output will be
Any code you want to execute after the request returns must be inside the callback; putting it physically “after” the
$.getJSONcall will not suffice. You should think of$.getJSONas “firing off” the JSON-getting process, then immediately returning to you; only later, when your script is done executing normal code and the server has responded, will the JavaScript event loop say “hey I got a response and am idle; time to call that callback that was waiting on the response!”Because of this, your
updateValuesfunction will need to accept a callback of its own in order to notify its own caller that the values have been updated; just callingupdateValueswill only fire off the value-updating process, and the values won’t be updated later until that idle time. Something like:Then calling code uses it as