2010-09-29 14 views
6

Tengo esta interesante función jQuery. Básicamente agrega un manejador de clics al enlace, y cuando se hace clic en él, cargará un formulario para permitirle al usuario editar el contenido. y el formulario es enviado por AJAX, y mostrará un mensaje de éxito cuando esté listo.JQuery/JavaScript: refactorización de funciones anidadas

El esquema está a continuación; No hace falta decir que esto es desordenado. Podría tener cada devolución de llamada como un método de clase. ¿Qué otras formas existen para refactorizar las funciones anidadas? También estoy interesado en ver si hay alguna manera de que las variables se declaran en una función madre todavía conservan su valor a la función anidada después de refactorización

$('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 
       } 
      }) 

     }) 

     }} 
    ) 
} 

Respuesta

4

Supongo que la parte interesante de su pregunta es cómo refactorizar sin perder el acceso a las variables de cierre.Aquí está mi sugerencia:

Versión uno: anidado, con cierres y acceso a variables:

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 
       } 
      }) 
      }) 
     } 
     }) 
    }) 

Versión dos: menos anidada, pero sin cierres y sin acceso variables:

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. 
}; 

versión de tres : menos anidado y con funciones y parámetros sin nombre para acceder a las variables de cierre:

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 
}; 
1

Puede refactorizar fácilmente esto para que sea mucho más fácil de leer. El concepto clave a comprender es que puede referirse a funciones con nombre tanto en devoluciones de llamada como anónimas. Así, por ejemplo:.

function clickHandler() { 
    alert("Link clicked"); 
} 
$('a').click(clickHandler); 

Mi preferencia es siempre para dar los nombres de las funciones de acuerdo con lo que hacen (por ejemplo loadImage, en lugar del caso de que usted tiene la intención de desencadenar ellos (por ejemplo clickLink Esto hace que el código más claro y Realiza cambios posteriores mucho más fácil En este caso, me gustaría estructurar mi código como el siguiente:..

$(document).ready(function(){ 
    $('a.edit').click(loadFormStart); 

    function loadFormStart() { // get form 
     $.ajax({ 
      success: loadFormEnd 
     }); 
    } 

    function loadFormEnd(data) { // add form & handler 
     $('new_form').submit(handleFormStart); 
    } 

    function handleFormStart() { // submit form 
     $.ajax({ 
      success: handleFormEnd 
     }); 
    } 

    function handleFormEnd(data) { // receive form data 
     //display message 
    } 
}); 

también me aconsejo que lea Code Organization on jqfundamentals que da un enfoque similar a esto usando un objeto literal

0

Interesante pregunta. Personalmente, no me importa lo anterior. Al comentar es la clave, por lo que podría considerar la clasificación de las llaves de cierre con cierta:

  } //success: function(data) 
     }) //$.ajax({ 
    }) //$(new_form).submit(

... etc

también me gustaría ver a la alineación de los soportes correctamente (en un primer momento Clance, su }} es un poco desconcertante)

Si se trata de estrategias de anidamiento 'genéricas', la única otra sugerencia que tengo es mover el código a otras funciones. Por supuesto, significa que tiene la función decalificada en la memoria, pero puede hacerlo más legible.

También podría considerar una estrategia específica relacionada con este código. Por ejemplo, en lugar de vincular manualmente un submit a new_form, ¿puede utilizar la función live de alguna manera para asegurarse de que se realice automáticamente?

En una nota sin relación, probablemente debería agregar un ; al final de cada una de las líneas entre corchetes.

+0

Re usando $(). live() - tenga cuidado, porque el evento de envío no burbujea en Internet Explorer. Supuestamente jQuery corrige este problema, pero descubrí que tenía que vincularme al evento click del botón de enviar, que obviamente no es la mejor solución. – lonesomeday

+0

Siempre me mantengo alejado de construcciones excesivamente anidadas. Además, cualquier IDE decente evita la necesidad de documentar los corchetes de cierre, ¡eso se ve realmente feo! –

Cuestiones relacionadas