0

I have the following javascript

// JavaScript Document
$("[name=students]").each(function(){

        var student_id  = $(this).attr("data-student_id");

        ///////////////////////////////////////////////////////////////////
        ajax_call = $.ajax({
            method: "POST",
            url: "/load.php",
            dataType: "html",
            async: true,
            beforeSend: function(){
            },
            data:   { 
                        student_id: student_id
                    },

            success: function( response ) 
            {   
                // dynamically add radio buttons
                // html response is radio buttons with NAME of as_xxxx inside of parent div[name=students] element already in the DOM
                $("[name=students][data-student_id='"+student_id+"']").fadeIn( "slow").html(response).show();

            },
            error: function(xhr, textStatus, errorThrown)
            {
                // show error message
            },
        });
        //END AJAX/////////////////////////////////////////////////////////////////
    }).promise().done( function(){ 

        save_data();
    });
});
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  SAVE
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function save_data()
{

    //$(document).on('click','[name=student][name^=as_]',function(event) // WORKS IF ajax ASYNC = TRUE

    $("[name=student][name^=as_]").on("click",function(event)  // DOES NOT WORK IF ajax ASYNC = TRUE.   Works if ASYNC = FALSE
    {
        // SAVE RADIO BUTTON DATA ON CLICK
    });
}
</javascript>

The code works fine if async is FALSE. But if asnyc is TRUE then I can't click any of the dynamically added radio buttons.

I am assuming that the promise().done code is firing BEFORE all the ajax synchronous requests are completed.

Is there a way to ensure a loops of synchronous ajax requests are completed?? OR why is the code not working?

Paul Flahr
  • 95
  • 12

2 Answers2

1

So to make multiple ajax requests, that have asynchronous nature of course, since we are dealing with http requests, you should consider a Promise.all wrapped with some logic in the promiseAll api. This example shows you how to make several async http calls and collect results, so you have something like

promiseAll(items, callback)
  .then((results) => {
    console.log(results)
  })
  .catch((error) => {
    console.log(error)
  });

where you will get in the then all the results from the http calls, while the callback will actually do the async job (it maybe every kind of async process actually).

// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest
SimpleRequest = {
  call: function(what, response) {
    var request;
    if (window.XMLHttpRequest) { // Mozilla, Safari, ...
      request = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // IE
      try {
        request = new ActiveXObject('Msxml2.XMLHTTP');
      } catch (e) {
        try {
          request = new ActiveXObject('Microsoft.XMLHTTP');
        } catch (e) {}
      }
    }
    // state changes
    request.onreadystatechange = function() {
      if (request.readyState === 4) { // done
        if (request.status === 200) { // complete 
          response(request.responseText)
        } else response();
      }
    }
    request.open('GET', what, true);
    request.send(null);
  }
}
//PromiseAll
// @author loretoparisi at gmail dot com
var promiseAll = function(items, block) {
  var promises = [];
  items.forEach(function(item, index) {
    promises.push(function(item, i) {
      return new Promise(function(resolve, reject) {
        return block.apply(this, [item, index, resolve, reject]);
      });
    }(item, index))
  });
  return Promise.all(promises);
} //promiseAll

promiseAll([...new Array(3)], (item, index, resolve, reject) => {
    console.log("Making request [" + index + "]")
    SimpleRequest.call('https://icanhazip.com/', function(result) {
      if (result) {
        console.log("Response[" + index + "] " + result);
        resolve(result);
      } else {
        reject(new Error("call error"));
      }
    })
  })
  .then((results) => {
    console.log(results)
  })
  .catch((error) => {
    console.log(error)
  });
loretoparisi
  • 15,724
  • 11
  • 102
  • 146
0

This works...solution from https://stackoverflow.com/a/5627301/1459802 Updated code:

    // JavaScript Document
    $("[name=areas]").each(function(){

            var student_id  = $(this).attr("data-student_id");
            var deferreds = [];
            ///////////////////////////////////////////////////////////////////
            deferreds.push( $.ajax({
                method: "POST",
                url: "/load.php",
                dataType: "html",
                async: true,
                beforeSend: function(){
                },
                data:   { 
                            //some data
                        },

                success: function( response ) 
                {   
                    // dynamically add radio buttons
                    // html response is radio buttons with NAME of as_xxxx inside of #container (parent element)
                    $("[name=areas][data-student_id='"+student_id+"']").fadeIn( "slow").html(response).show();

                },
                error: function(xhr, textStatus, errorThrown)
                {
                    // show error message
                }
            }) //END AJAX/////////////////////////////////////////////////////////////////
            );

        }); // .each


         $.when.apply(null, deferreds).done(function() {
              console.log("*************** DONE *****************");
             save_data();
            });    
    });
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  SAVE
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    function save_data()
    {

        //$(document).on('click','#container [name^=as_]',function(event) // WORKS IF ajax ASYNC = TRUE

        $("[name=areas][name^=as_]").on("click",function(event)  // DOES NOT WORK IF ajax ASYNC = TRUE.   Works if ASYNC = FALSE
        {
            // SAVE RADIO BUTTON DATA ON CLICK
        });
    }
Umair Khan
  • 1,684
  • 18
  • 34
Paul Flahr
  • 95
  • 12