Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery/JavaScript : refactoring nested functions

I have this interesting jQuery function. It basically adds a click handler to link, and when that is clicked, it will load a form to allow the user to edit the content. and the form is submitted by AJAX, and will display a success message when it's done.

The outline is below; needless to say, this is messy. I could have each of the callback as a class method. What other ways are there to refactor nested functions? I am also interested to see if there are ways that variables declare in a parent function still retain its value down to the nested function after refactoring

$('a.edit').click( function() {

   // ..snipped..
   // get form
   $.ajax({
       success: function() {

         // add form
         // submit handler for form
         $(new_form).submit(function() {

            // submit via ajax
            $.ajax({

                success: function(data) {
                    // display message
                }
            })

         })

       }}
   )
}
like image 358
Extrakun Avatar asked Sep 29 '10 07:09

Extrakun


1 Answers

I guess the interesting part of your question is how to refactor without loosing access to the closure variables. Here is my suggestion:

Version one: nested, with closures and variable access:

   var a;
    $('a.edit').click( function() {
      var b;
      $.ajax({
        success: function() {
          var c;
          $(new_form).submit(function() {
            var d;
            $.ajax({
                success: function(data) {
                   // a,b,c,d are all visible here.
                   // note that a references the same object for all calls of the success function, whereas d is a different variable for each call of submit.
                   // this behaviour is called closure: the 'enclosed' function has access to the outer var
                }
            })
          })
        }
      })
    })

Version two: less nested, but without closures and without variable access:

var a;
$('a.edit').click(onEdit);

var onEdit = function() {
  var b;
  $.ajax({success: onEditSuccess});
};

var onEditSuccess = function() {
  var c;
  $(new_form).submit(onSubmit);
};

var onSubmit = function() {
  var d;
  $.ajax({success: onSubmitSuccess});
}

var onSubmitSuccess = function(data) {
  // a is visible (global var)
  // b,c,d NOT visible here.
};

Version three: less nested and with unnamed functions and parameters to get access to the closure variables:

var a;
$('a.edit').click(function(){onEdit(a)});

var onEdit = function(a) {
  var b;
  $.ajax({success: function(){onEditSuccess(a,b)}});
};

var onEditSuccess = function(a,b) {
  var c;
  $(new_form).submit(function(){onSubmit(a,b,c)});
};

var onSubmit = function(a,b,c) {
  var d;
  $.ajax({success: function(data){onSubmitSuccess(data,a,b,c,d)}});
}

var onSubmitSuccess = function(data,a,b,c,d) {
  // a,b,c,d are visible again
  // nice side effect: people not familiar with closures see that the vars are available as they are function parameters
};
like image 122
tec Avatar answered Oct 26 '22 18:10

tec