0

Please excuse the awkward title I'll try my best to explain my peculiar problem.

I have three bits of javascript code:

  • Some self executing code which calls my personal Ajax function and passes it a callback.
  • The ajax function itself which retrieves the data calls the callback passing it the data.
  • The callback itself which takes in the data and parses it into an array of n length.

What should be noted is that the self executing code and the callback function are defined within their own closure. The ajax function is accessed through an imported named closure which I defined as $.

I am fairly new to JavaScript and I am still learning about closures and their scopes. I have reason to believe that this problem is probably related to that.

Anyway, my problem relates to trying to access that supposedly populated array. Since I defined the array in a suitable scope (or so I believe) as the parse function I think I should have no problem pushing items into it.

This is self exectuting :

(function ($){

    //Load stock
var items = [];
var response = $.Ajax("scripts/Lookup.php","GET",parse);

function parse(a){
    for(/*Simplified view*/){
        var item = new $.Item();
        item.name = domStuff.textContent;
        item.description = domStuff.textContent;
        item.price = domStuff.textContent;
        item.id = domStuff.textContent;

        items.push(item);
    }
}

    //Test the length (and verify contents)
    for(var i=0; i < items.length; i++){
        alert(items[i].price);
    }
}($));

This is my definitions, which includes the Ajax function:

var $ = (function(){
var s = {};

    var ajax = function(url,method,callback){
        var a = new XMLHttpRequest();
        a.open(method, url, true);
        a.onreadystatechange = function(){
        if(this.readyState==4){
                callback(a);
            }
    }
    a.send();
    };

    s.Ajax = (function(){
        return ajax;
    }());

return s;
}());

So what justifies the title is that when I probe the code with firebug, I can see that items is populated with 3 Objects correctly defined by the parsed data.

The loop then alerts as intended 3 times.

However, if I remove the break points and have firebug ignore the code then the loop doesn't play out and I can only assume that the array is empty.

The code works also if I alert(items) prior to the test loop.

2
  • Where can I find this special version of Firebug? Commented Apr 20, 2011 at 17:01
  • If looks like code synchronous issue. The only variable that happens when you use Firebug of Alert is a delay. It seems that delay gives breathing time for some of your code to complete. ( I have not completely analyzed your code, but this is the first thing that came to me). Commented Apr 20, 2011 at 17:03

3 Answers 3

2

AJAX is filling items asynchronously, meaning in your closure, on first execution items.length will be zero (from the original array initialization). Over time, AJAX through calls to your parse method will fill this array.

Because you're keeping items in a closure, you won't actually be able to access it from outside - which is a good practice, but can cause problems with debugging! Instead of items.push(item) try alert(item) (any browser, but execution blocking) or console.log(item) (firebug only) to see that you are, indeed, getting the results back from AJAX just not in initial execution.

Sign up to request clarification or add additional context in comments.

2 Comments

This is what I was trying to say as well in my answer. Your code needs to wait for the asynchronous code to finish.
Thanks, the problem was regarding the asynchronicity.
1

I'm not a JavaScript expert by any means. However, I have run into situations on other programming languages where debugging has solved an issue.

In those cases, debugging has slowed the code down enough for it to work. Some process A needs asynchronous process B to return an object or do something before executing beyond a certain point. What is most likely happening in these types of scenarios is that the main thread is continuing or not waiting for the object to be populated by the other routine.

I hope that helps.

Comments

1

Your parse function is called asynchronously. You need to wait for the parse function to be called before testing it.

Either test the result in you parse function or have another function as the callback for ajax call. This function calls parse and then test the results.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.