2010-03-30 16 views
15

Tenemos esta función anónima en nuestro código, que es parte de los parámetros del objeto Ajax de jQuery y que utiliza algunas variables de la función a la que se llama.Cómo refactorizar esta función anónima de Javascript?

this.invoke = function(method, data, callback, error, bare) { 
     $.ajax({ 
     success: function(res) { 
      if (!callback) return; 

      var result = ""; 
      if (res != null && res.length != 0) 
       var result = JSON2.parse(res); 

      if (bare) 
      { callback(result); return; } 

      for (var property in result) { 
       callback(result[property]); 
       break; 
      } 
     } 
    }); 
} 

He omitido el código adicional, pero ya se ha hecho. El código funciona perfectamente bien, pero filtra 4 Kbs en cada llamada en IE, por lo que quiero refactorizarlo para convertir la función anónima en una función con nombre, como this.onSuccess = function (res) {..}.

El problema es que esta función usa variables de this.invoke (..), así que no puedo simplemente sacarlo de su cuerpo. ¿Cómo puedo refactorizar correctamente este código, para que no use funciones anónimas y variables de función principal?

Actualización. Estoy pensando en crear un objeto separado, inicializándolo con los mismos parámetros y pasar su función onSuccess como parámetro para el objeto Ajax de jQuery. Aunque sospecho que todavía perderá memoria.

Actualización 2. He encontrado algunos enlaces que sugieren que la fuga real podría ser causada por jQuery. Simple jQuery Ajax call leaks memory in Internet Explorer Memory leak involving jQuery Ajax requests

Aun así, era bueno para encontrar una manera de refactorizar esto.

Actualización 3. Voy a esperar una solución más genérica, antes de aceptar una respuesta.

+0

¿Cómo se puede saber que esto se está escapando realmente, en lugar de no recogerse de inmediato? Las filtraciones de IE tienden a estar alrededor de las referencias circulares entre los elementos DOM y los controladores de eventos, ninguno de los cuales está obviamente presente aquí. –

+0

IE también se filtra en los cierres, que es lo que tenemos aquí. He depurado el código anterior y, según mi conocimiento, esta es una de las partes donde se produce la fuga, ya que la devolución de llamada no pierde nada. (Para ser justos, todas las filtraciones de navegador en este código). –

Respuesta

10

Puedes añadir params adicionales a la petición Ajax que se puede acceder en la devolución de llamada de éxito:

this.invoke = function(method, data, callback, error, bare) { 
    $.ajax({ 
     success: onSuccess, 
     invokedata: { 
     callback: callback, 
     bare: bare 
     } 
    }); 
}; 

var onSuccess = function(res) { 
    var callback = this.invokedata.callback, 
     bare = this.invokedata.bare; 
    if (!callback) return; 

    var result = ""; 
    if (res != null && res.length != 0) 
     var result = JSON2.parse(res); 

    if (bare){ 
     callback(result); 
     return; 
    } 

    for (var property in result) { 
     callback(result[property]); 
     break; 
    } 
} 
+0

No sabía que podía hacer eso, gracias. Verifico si aún hay una fuga. –

+0

¿Cómo se está transfiriendo a res en success? – plodder

+0

De jquery. http://api.jquery.com/jQuery.ajax/ –

4

+1 por excelente, excelente pregunta - Siento tu dolor, esto está muy bien considerado como es.

Una sugerencia (y tal vez esto es lo que quería decir con su actualización) ... defina un contenedor para onSuccess y haga que devuelva la función que desea asignar. Luego llame a la función externa y asígnela a la opción "éxito", pasando los valores que necesita. Esos valores serán preasignados a las variables en la función interna. En realidad no estoy seguro si esto ayudará - todavía se termina con una función anónima - pero vale la pena intentarlo

this.invoke = function(method, data, callback, error, bare) { 
    $.ajax({ 
     success: onSuccess(callback, bare); 
    }); 
}; 

var onSuccess = function(callback, bare) { 
    return function() { 
     if (!callback) return; 

     var result = ""; 
     if (res != null && res.length != 0) 
      var result = JSON2.parse(res); 

     if (bare) 
     { callback(result); return; } 

     for (var property in result) { 
      callback(result[property]); 
      break; 
     } 
    } 
} 
+2

Esta es una buena manera desde el punto de vista de la programación, pero no ordena el problema de la fuga, ya que su función anónima en la declaración de retorno aún hace referencia a variables de la función primaria. –

+0

OK ... como me temía. Si es * realmente * la creación de funciones anónimas después de cada llamada ajax que causa la pérdida de memoria, entonces estás en un aprieto. No estoy seguro de qué es lo que impide la recolección de basura aquí: ¿ha intentado eliminar físicamente la función cuando termina con ella? – plodder

Cuestiones relacionadas