deshacerse del anidamiento requerido para las devoluciones de llamada de javascript
Frecuentes
Visto 78 equipos
0
Tengo algunas funciones de javascript que realizan solicitudes asincrónicas a través de la red y reciben una devolución de llamada para "devolver" datos a través de. Aquí hay un ejemplo de cómo se ve esto cuando lo uso:
RemoteQuery(server,query,function(ret) {
// do something with ret
})
El problema es que si tengo varias consultas seguidas, el código se vuelve bastante anidado y difícil de administrar. Dado que confío en variables de alcance, tampoco puedo extraer cada una de estas funciones en una función de nivel superior separada. Aquí hay un ejemplo de juguete:
RemoteQuery(server,query1,function(ret) {
var x = ret[5]
RemoteQuery(server,query2,function(ret) {
var y = ret[3]
if (x + y > 10) {
RemoteQuery(server,query2,function(ret) {
// do more stuff
})
}
})
})
Obviamente, si tengo más de 2 o 3 consultas, comienza a ponerse feo, ¡y podría tener muchas más que eso!
Idealmente, me gustaría representar lo anterior sin todo ese anidamiento, por ejemplo
ret = RemoteQuery(server,query1)
var x = ret[5]
ret = RemoteQuery(server,query2)
var y = ret[3]
if (x + y > 10) {
ret =RemoteQuery(server,query2)
// do more stuff
}
pero lo único que he pensado que podría funcionar sería analizar el javascript, reconocer funciones que tienen devoluciones de llamada, volver a escribirlas en la forma correcta y eval, pero esto parece terriblemente complicado y dificultaría mucho la depuración.
¿Hay un mejor mecanismo para hacer esto?
3 Respuestas
1
La forma 'adecuada' de hacerlo es escribir declaraciones de función para ellos y evitar depender de las variables con ámbito (así que páselas a cada función). Algo como:
var myFunc1 = function(x, ret1) {
RemoteQuery(server, query, function(ret2) {
var y = ret[3];
myFunc2(x, y, ret2);
});
};
var myFunc2 = function(x, y, ret) { /* do more stuff */ };
RemoteQuery(server, query, function(ret1) {
var x = ret[5];
myFunc1(x, ret1);
});
Como tiene que llamar a esas consultas remotas de forma asincrónica, no hay forma de hacer la solución que sugiere en su pregunta. Uso de la Deferred
El objeto puede funcionar, pero creo que aún tendría que reestructurar sus funciones (ya que su objetivo es evitar el anidamiento).
Respondido el 30 de junio de 12 a las 20:06
Para cualquier persona que haga referencia a esto en el futuro, elegí este modelo cuando aprendí NodeJS, ya que así es como se construyen la mayoría de las aplicaciones de demostración/ejemplo (Node generalmente requiere mucho anidamiento). - bob davies
0
¿Qué tal una matriz de funciones encadenadas?
function R1 (server, query, callback)
{
RemoteQuery(server, query, function(ret) {
// process ret
if (x + y > 10)
callback();
}
}
function R2 (server, query, callback)
{
RemoteQuery(server, query, function(ret) {
// process ret
callback();
}
}
function R3 (server, query, callback)
{
RemoteQuery(server, query, function(ret) {
// process ret
callback();
}
}
var functions = [R1, R2, R3]
function callAll(a, server, query)
{
var callNext = function(callback, i)
{
if (i < a.length)
a[i](server, query, function() { callback(callback, i + 1); });
}
callNext(callNext, 0);
}
callAll(functions, 'server', 'query');
Respondido el 30 de junio de 12 a las 20:06
de esta manera no necesitas todos esos jquerys y dojos, etc. ;] - Kuba Wyrostek
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas javascript or haz tu propia pregunta.
¿Qué tal una matriz de funciones? - Kuba Wyrostek
jQuery tiene esto
Deferred
técnica que puede ayudarte, pero no sé si está bien que la uses. - MaxArt