The jQuery.when method accepts a dynamic number of arguments, however, it does not accept an array of arguments. This tutorial show you how to get around that issue. The jQuery.when method accepts a dynamic number of deferred objects. If you know how many objects you are passing in, it is very easy to do so manually. However, if you have a dynamic number of objects that you need to pass in, it isn't as straight-forward.

Take the following html as an example. Each div has a data attribute that contains a url to a page that needs to be loaded into it.

view plain print about
1<div class="dynaload" data-load-url="/foo.html"></div>
2<div class="dynaload" data-load-url="/foo1.html"></div>
3<div class="dynaload" data-load-url="/foo2.html"></div>
4<div class="dynaload" data-load-url="/foo3.html"></div>
5<div class="dynaload" data-load-url="/foo4.html"></div>

Now, if you knew for a fact that you would always have five divs, it would be easy to just pass in each one manually.

view plain print about
1var $ajaxdivs = $(".dynaload");
2$.when(
3$.ajax({
4    url: $ajaxdivs.eq(0).data("loadUrl"),
5    success: function(html) {
6        $ajaxdivs.eq(0).html(html);
7    }
8}), $.ajax({
9    url: $ajaxdivs.eq(1).data("loadUrl"),
10    success: function(html) {
11        $ajaxdivs.eq(1).html(html);
12    }
13}), $.ajax({
14    url: $ajaxdivs.eq(2).data("loadUrl"),
15    success: function(html) {
16        $ajaxdivs.eq(2).html(html);
17    }
18}), $.ajax({
19    url: $ajaxdivs.eq(3).data("loadUrl"),
20    success: function(html) {
21        $ajaxdivs.eq(3).html(html);
22    }
23}), $.ajax({
24    url: $ajaxdivs.eq(4).data("loadUrl"),
25    success: function(html) {
26        $ajaxdivs.eq(4).html(html);
27    }
28})).then(function() {
29    alert("All Done Loading!");
30});

However, lets consider what that does to our code if the number of divs are dynamic. We can't pass an array into jQuery.when because it can't accept an array. We can't use a for loop to pass them in because they all have to be passed in at once to be part of the same deferred object. You could use server-side code to loop through it, however that co-mingles server-side code and client-side code which typically is not a good idea. This leads us to the point of this tutorial: Using jQuery.when with a dynamic number of objects. In order for us to pass in a dynamic number of objects to the jQuery.when method, we're going to generate an array of deferred objects that need to be passed to the jQuery.when method. Next, we'll take advantage of the function.prototype.apply method that exists on all JavaScript functions. The function.prototype.apply method accepts two parameters. The first parameter will be available as "this" within the function, and the second parameter is an array of arguments. This is how we get around the limitation of jQuery.when not accepting an array of objects.

view plain print about
1var deferredArr = $.map($(".dynaload"), function(el, i) {
2    return $.ajax({
3        url: $(el).data("loadUrl"),
4        success: function(html) {
5            $(el).html(html);
6        }
7    });
8});
9$.when.apply(this, deferredArr).then(function() {
10    alert("All Done Loading!");
11});

Even if you know beforehand how many divs you were working with, this way of doing it is better in the long run because it will allow you to add more divs without having to update the JavaScript, and it comes with the added benefit of requiring less code.