Como refatorar esta função anônima Javascript?
-
23-09-2019 - |
Pergunta
Temos essa função anônima em nosso código, que faz parte dos parâmetros do objeto Ajax do jQuery e que utiliza algumas variáveis da função de onde é chamada.
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;
}
}
});
}
Omiti o código extra, mas você entendeu.O código funciona perfeitamente bem, mas vaza 4 Kbs em cada chamada no IE, então quero refatorá-lo para transformar a função anônima em uma função nomeada, como this.onSuccess = function(res) { ..}.
O problema é que esta função usa variáveis de this.invoke(..), então não posso simplesmente tirá-la de seu corpo.Como refatorar corretamente esse código, para que ele não usar funções anônimas e variáveis de função pai?
Atualizar. Estou pensando em criar um objeto separado, inicializá-lo com os mesmos parâmetros e passar sua função onSuccess como parâmetro para o objeto Ajax do jQuery.Embora eu suspeite que ainda haverá vazamento de memória.
Atualização 2. Encontrei alguns links sugerindo que o vazamento real pode ser causado pelo jQuery.Chamada jQuery Ajax simples vaza memória no Internet Explorer Vazamento de memória envolvendo solicitações jQuery Ajax
Ainda assim, foi bom encontrar uma maneira de refatorar isso.
Atualização 3. Vou esperar por uma solução mais genérica antes de aceitar uma resposta.
Solução
Você pode adicionar parâmetros extras à solicitação ajax que podem ser acessados no retorno de chamada de sucesso:
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;
}
}
Outras dicas
+1 para uma pergunta excelente e excelente - sinto sua dor - isso já está muito bem contabilizado.
Uma sugestão (e talvez seja isso que você quis dizer com sua atualização)... defina um wrapper para onSuccess e faça com que ele retorne a função que você deseja atribuir.Em seguida, chame a função externa e atribua-a à opção "sucesso", passando os valores necessários.Esses valores serão pré-atribuídos às variáveis na função interna.Na verdade, não tenho certeza se isso vai ajudar - você ainda terá uma função anônima - mas vale a pena tentar
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;
}
}
}