title: Deferred Objects: Call Function after Single Ajax Call with Nested Looping Ajax Calls Done
body: <p>I have a single Ajax function which returns an array of objects.  I then utilize this array of objects to dictate each of the following child Ajax calls.  I append the results of the child Ajax calls to an element created by the parent.  I would like to use a Deferred object(s) and call a third function, but only when all Ajax calls are completed in both the child and parent functions.</p>
  
  <p>Where am I going wrong, and is there a more effective implementation to accomplish this functionality?</p>
  
  <p>HTML:</p>
  
  <pre><code>&lt;div class="out"&gt;&lt;/div&gt;
  &lt;button id="display"&gt;display&lt;/div&gt;
  &lt;button id="clear"&gt;clear&lt;/div&gt;
  </code></pre>
  
  <p>JavaScript:</p>
  
  <pre><code>$(document).ready(function(){
  
    var lib = {};
  
    lib.func3 = function(){
  
        alert("Success!  Func3 wasn't called until all Ajax calls were completed.")
  
    }
  
    lib.func2 = function(elem, userObj){
  
      var root = 'http://jsonplaceholder.typicode.com';
      return $.ajax({
        url: root + '/posts?userId=' + userObj.id,
        method: 'GET',
        success: function(data){
          var ol = $("&lt;ol/&gt;")
          $(data).each(function(i){
            var elem = $("&lt;li/&gt;").html(data[i].title);  
            $(ol).append(elem);
          });
          elem.append(ol);
        }
      }); 
  
    }
  
    lib.func1 = function(){    
  
      var func1_deferred_obj = $.Deferred();
      var func2_promises = [];
  
      var root = 'http://jsonplaceholder.typicode.com';
      $.ajax({
        url: root + '/users',
        method: 'GET',
        success: function(data){
  
          var ol = $("&lt;ol/&gt;");
  
          $(data).each(function(i){
            var elem = $("&lt;li/&gt;").html(data[i].name);  
            $(ol).append(elem);
            var func2_deferred_obj = lib.func2(elem, data[i])
            func2_promises.push(func2_deferred_obj);
          });
  
          $(".out").append(ol)
  
        }
      })
  
      $.when.apply($, func2_promises).done(function(){func1_deferred_obj.promise()})
      return func1_deferred_obj;
    }
  
    $("#display").click(function(){
  
      $(this).unbind("click");
  
      $.when(lib.func1()).done(function(){
        lib.func3();
        $("#display").bind('click');
      })
  
    })
  
    $("#clear").click(function(){ $(".out").empty(); })
  
  });
  </code></pre>
  
  <p>CODEPEN: <a href="http://codepen.io/dclappert/pen/epBLEB?editors=101" rel="nofollow">http://codepen.io/dclappert/pen/epBLEB?editors=101</a></p>