JavaScript Seems to Stop After AJAX Call

The question title is rather vague, but here's my situation. I have roughly 700+ lines of jQuery for a web application, each function and "major point of interest" in the code noted by a log to the console when it fires. For example, I have a few functions that use an AJAX call to a servlet to retrieve some information. I log when the AJAX request begins, if it's succeeded (then print what data it gathered), etc. So, by the look of what my console has logged when I open the page, it seems to stop after the first AJAX call. Granted, the call seemed to work just fine, and the data it returned was perfect. As you'll see, it even populated the select box as intended. However, the console logs stop shortly after, making me believe that for some reason, the other functions are not being called...

jQuery
$(document).ready(function() {
    Initialize();
});
function Initialize() {
    console.log("Initializing...");
    User();
    Widgets();
    if($.cookie("fogbugzId") != null) {
        console.log("Stored ID: " + $.cookie("fogbugzId"));
        $("#userSelect").val($.cookie("fogbugzId")).trigger("change");
        $("#userSelect").hide();
    } else console.log("No ID Stored!");
}
function User() {
    console.log("Initializing User...");
    $.each(FetchUsers(), function(index, user) {
        $("#userSelect").append($("<option>").val(user.id).text(user.name));
    });
    $("#userSelect").change(function() {
        if($("#userSelect").val() != "") {
            console.log("User Changed to " + $("#userSelect").val() + ": " + $("#userSelect").text());
            $.cookie("fogbugzId", $("#userSelect").val(), { expires: 365 });
        }
        Update();
    });
    console.log("User Initialized!");
}
function FetchUsers() {
    console.log("Loading Users...");
    $("#loading").show();
    $.get(servlet, { command: "getUsers" }, function(data) {
        var users = new Array();
        $(data).find("user").each(function() {
            users.push({
                id: $(this).find("id").text(),
                name: $(this).find("name").text()
            });
        });
        $.each(users, function(index, user) {
            console.log(">> " + user.id + ": " + user.name);
        });
        console.log("Users Loaded!");
        return(users);
    }, "xml").complete(function() {
        $("#loading").hide();
    }).error(function() {
        console.log("Loading Users Failed!");
    });
}
function Widgets() {
    console.log("Initializing Widgets...");
    // More Code
    console.log("Widgets Initialized!");
}
Console
Initializing...
Initializing User...
Loading Users...
>> 267: Alex Molthan
>> 35: Bill Brinkoetter
>> 100: Bob Yoder
>> 189: Brian Cutler
>> 559: Brian Ormond
>> 400: Corey Nakamura
Users Loaded!

But the logging stops right there. So the AJAX call to fetch the users from the database works fine, but apparently the User() function doesn't manage to finish properly. The only error that the JavaScript console gives me is one within my jquery.min.js file:

Uncaught TypeError: Cannot read property 'length' of undefined  jquery.min.js:16
    f.e.extend.each                                             jquery.min.js:16
    User                                                        modifytime.js:14
    Initialize                                                  modifytime.js:3
    (anonymous function)                                        modifyTime.jsp:21
    f.extend._Deferred.e.resolveWith                            jquery.min.js:16
    f.e.extend.ready                                            jquery.min.js:16
    f.c.addEventListener.B                                      jquery.min.js:16

It looks as though it is breaking on the $.each() that iterates through the array of users returned by the FetchUsers() function. I know the function returns usable array, so I'm not sure what it's getting stuck on. Can anyone see something I'm missing right off the bat? I tried assigning the users[] returned by the FetchUsers() function into a variable first, then passing that into the $.each(), but it still didn't work. Any suggestions?

Edit: After replacing the minified version of jQuery with the uncompressed version, it seems as though the array of users that I pass into the $.each() function has now .length property, which is why it's breaking. Just to check, before I call that particular $.each() function, I placed a log of the users[].length returned from the FetchUsers() function to see that it still had no .length property. I then went to the FetchUsers() function itself and placed a log of the users[].length just before I return it. This log, however, works perfectly fine (though my example doesn't show it, it returns 40 users). So is my users[] not being returned as an array or something?

Answers


FetchUsers does not return anything, it does not even have a return statement. Additionally, $.get is an asynchronous function, so you cannot return the value it passes to its callback from the FetchUsers function. Instead, you could make FetchUsers take a callback it calls when it has received data of a user (and in this case doing that change would be relatively trivial):

function User() {
    console.log("Initializing User...");
    FetchUsers(function(user) { // Changed!
        $("#userSelect").append($("<option>").val(user.id).text(user.name));
    });
    <...>
}

function FetchUsers(callback) { // Changed!
    console.log("Loading Users...");
    $("#loading").show();
    $.get(servlet, { command: "getUsers" }, function(data) {
        //var users = new Array(); No longer necessary.
        $(data).find("user").each(function() {
            callback({ // Changed!
                id: $(this).find("id").text(),
                name: $(this).find("name").text()
            });
        });
        <...>
}

Changing those three lines with the "Changed!" comment should be enough to make it work correctly. (Though your logging of the users gotten will need to be slightly altered as they are no longer pushed into an array.)


I confess I have not read and understood every part of your source (nor checked if all the braces are closed), but FetchUsers clearly does NOT return anything (contrary to your claim) - so a call to FetchUsers() evaluates to 'undefined'. Fixing it will require some rewriting as in Javascript you cannot really return a result of asynchronous operation (like $.get) from a synchronous function (like FetchUsers()) - this would require multithreading (some kind of blocking, waiting etc).


Need Your Help


About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.