Travis Heeter Travis Heeter - 1 month ago 8
jQuery Question

$.when not finishing before running done

I need to get the contents of each file in an array via AJAX, analyze them, then put the results in an array. However, JS skips over my AJAX calls seemingly no matter what. I'm trying to use JQuery's when to make it wait, but it doesn't seem to be working:

$.when(
// Send a request for each file
$.map(fileNameArray, function(fileName,i){
$http.get(path + fileName).then(function(file) {
// analyze the results (takes some time)
var analysis = analyze(file)
$log.log("analysis: " + analysis)
return analysis
})
})
).then(function(x){
// I want this to run only after $.map is finished
$log.log("x: " + x)
})


I get this result:

x:
analysis: > Object...


However, I'm expecting to see this:

analysis: Object...
x: Array [...]


Am I using $.when incorrectly? Is there a better way to do this? Possibly with Angular?

Answer

In jQuery's infinite wisdom, $.when() does not accept an array as an argument which is what $.map() provides. Instead, $.when() needs separate arguments.

So, you can use .apply() to pass the arguments as $.when() requires.

$.when.apply($, $.map(...)).then(...)

In addition, you also have to return the $http.get() promise from within the $.map() callback. So, change to this:

$.when.apply($,
    // Send a request for each file
    $.map(fileNameArray, function (fileName, i) {
        return $http.get(path + fileName).then(function (file) {
            // analyze the results (takes some time)
            var analysis = analyze(file);
            $log.log("analysis: " + analysis)
            return analysis;
        });
    });
).then(function(arg1, arg2, arg3) {
    // results are in separate arguments here 
});

Even better would be to remove the jQuery promises from this entirely and use Angular's $q.all().

$q.all(fileNameArray.map(function(fileName, i) {
    return $http.get(path + fileName).then(function(file) {
        // analyze the results (takes some time)
        var analysis = analyze(file);
        $log.log("analysis: " + analysis)
        return analysis;
    });
})).then(function(results){
    // array of results here
    $log.log(results)
})