1

I have two function, one function is a reload function that does a ajax web call to get data. the other is the item loader that loads the data. The problem is that the function that loads the data item has not value yet because of the ajax call made. Anyway of fixing this besides calling setTimeout? Thanks in advance for any help.

function reload(index) {
    _ListData[index] = null;
    DisplayInformation.GetTemplateTableInformation(
        ListManager.listReportId(),
        ListManager.listParameters(),
        ListManager.listSortParams(),
        TableReportHelper_TemplateRelatedAction,
        reloadRange.min, 
        reloadRange.num,
        function(templateItemIfo) {//success callback causes issues with race conditon in the function itemLookaheadCallback because _ListData[index] = null;
            itemLookaheadCallback(templateItemIfo, index);
        });
}

Here is the function that tries to load the item that was called in the reload callback

 function loadDataCallback(lookAheadData, index, loadNeighbors) {
    //Store the received value
    var item = _ListData[index];//this will be null because of _ListData[index] = null;
    item.data = lookAheadData.TemplateInformation;

};
user516883
  • 8,868
  • 23
  • 72
  • 114
  • 1
    could you reduce your code to just the essential to the question? – Marcelo Diniz Feb 03 '12 at 16:17
  • +1 to above. Missing context. Describe this problem in a more generic fashion. – Lior Cohen Feb 03 '12 at 16:24
  • Sorry about that, I reduced the code a little the line var item = _ListData[index]; will be null and thats the problem. the function reload callback itemLookaheadCallback does not set the index item fast enough. – user516883 Feb 03 '12 at 16:26
  • I don't think it is possible to answer within the context of this question because we don't know what any of these functions do. However, as a general rule you should not have a function that relies on the response of a xmlHttpRequest that isn't in some way called via the onreadystatechange listener of that request. If you follow that rule you will not have race conditions. – nwellcome Feb 03 '12 at 16:27
  • Saying that there's a [race condition](http://stackoverflow.com/a/34550/201952) is incorrect because JavaScript is single-threaded; there cannot be a race condition in a JavaScript program. – josh3736 Feb 03 '12 at 16:43
  • @josh3736, you're correct - this isn't a race condition (though look up web workers, you can use threads in js now) it's not using event based programming correctly. – nwellcome Feb 03 '12 at 17:11
  • Which piece of code sets _ListData[index]? Until you show us that, we can't help with why it's null when you expect it to have a value. – jfriend00 Feb 03 '12 at 17:20
  • @nwellcome: Even with web workers, all state is marshalled between threads (data is passed via events), so there's still no such thing as a race condition in JS because a worker thread never directly accesses data on another thread. – josh3736 Feb 03 '12 at 17:44

3 Answers3

2

Put the code to load the items inside the "success callback".

Alternatively, make the AJAX call synchronous, although this should be avoided because on slow connections or for large amounts of data it may appear like your page has frozen.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
0

I know this looks like a race condition, but I'm going to go out on a limb and suggest that it's actually a scope issue.

_ListData exists inside of the reload() function, and if I recall correctly a callback might inherit that scope and still make it accessible one level deep.

function reload(index) {
    _ListData[index] = null;
    ...
}

But the callback of a callback (which it looks like you might be doing) will probably loose that scope and exist in a completely anonymous scope.

reload -> itemLookaheadCallback -> loadDataCallback

The solution? Consider using window to define a globally accessible location for that variable. (window is always global).

Here's the changes that would make that happen:

function reload(index) {
    window._ListData[index] = null;
    ...
}

function loadDataCallback(lookAheadData, index, loadNeighbors) {
    var item = window._ListData[index];
    ...
};

Anyway, that's just a guess. Probably wrong, but relatively easy to verify.

Garrett Bluma
  • 1,312
  • 10
  • 14
-1

You can make a synchronous call by using async=False in your ajax call. for example:

$.ajax({
            type: 'GET',
            url: '/yourUrl/',
             dataType: 'json',
            success: function(data) {

            },
            data: {},
            async: false
        });

p.s.: Using jQuery to make Ajax call here.

Sid
  • 7,511
  • 2
  • 28
  • 41