2009-09-21 11 views
16

Hola a todos. Tengo, lo que parece ser, un problema trivial. Tengo el siguiente JavaScript:jQuery: ¿espera a que se complete la función para continuar procesando?

$(function() { 
    var r = GetResults(); 

    for(var i = 0; i < r.length; i++) { 
     // Do stuff with r 
    } 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 
     return data; 
    }); 
} 

Debido al hecho de que estoy llamando a un método de forma asíncrona, la secuencia de comandos continúa ejecutándose y cuando se encuentra con el bucle for, r, obviamente, no va a tener un valor aún. Mi pregunta es: cuando tengo un método que está haciendo una operación asincrónica, y dependo de los datos que devuelve en el bloque principal, ¿cómo detengo la ejecución hasta que se devuelven los datos? Algo como:

var r = GetResults(param, function() { 

}); 

donde la función es una función de devolución de llamada. No puedo mover el procesamiento de bucle for a la función de devolución de llamada de la solicitud JSON porque estoy reutilizando la funcionalidad de GetResults varias veces en toda la página, a menos que desee duplicar el código. ¿Algunas ideas?

Respuesta

13

mueva su bloque "do stuff with r" en su devolución de llamada $ .getJSON. no puede hacer cosas con r hasta que haya sido entregado, y la primera oportunidad que tendrá de usar r es en la devolución de llamada ... entonces hágalo en ese momento.

$(function() { 
    var r = GetResults(); 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 
     for(var i = 0; i < data.length; i++) { 
      // Do stuff with data 
     } 
     return data; 
    }); 
} 
+0

Gracias por la respuesta. La razón por la que dividí GetResults fue porque estoy reutilizando esa funcionalidad varias veces en toda la página. Debería editar mi publicación para decir eso. – user135383

+0

si necesita hacer el mismo procesamiento en datos provenientes de múltiples lugares, solo reemplace su función de devolución de llamada con una función nombrada y realice el procesamiento allí. $ .getJSON ("/ controller/method /", null, processData (data)); function processData (d) {...} –

3

usted puede hacer esto:

$(function() { 
    PerformCall();   
}); 

function PerformCall() { 
    $.getJSON("/controller/method/", null, function(data) { 
     for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
     } 
    }); 
} 
0

Esto no es posible.

O hace que su función sea síncrona o cambia el diseño de su código para admitir la operación asincrónica.

0

Mover el procesamiento de datos en la devolución de llamada:

$(function() { 
    GetResults(); 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 

     for(var i = 0; i < data.length; i++) { 
      // Do stuff with data 
     } 
    }); 
} 
+0

esto no funcionará. su declaración de devolución regresará de la devolución de llamada, no de GetResults. Esta solución nunca funcionará ya que no usa callbacks correctamente – mkoryak

+0

@mkoryak Gracias. Eliminé el retorno de la devolución de llamada. – ctford

7

Ajax ya se le da una devolución de llamada, que se supone que usarlo:

function dostuff(data) { 
    for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
    } 
}; 
$(document).ready(function() { 
    $.getJSON("/controller/method/", null, dostuff); 
}); 
2

La respuesta corta es que no se puede bloquear en una operación asíncrona ... que es, por supuesto, el significado de "asíncrono".

En su lugar, debe cambiar el código para usar una devolución de llamada para activar la acción en función de los datos devueltos por la llamada $.getJSON(...). Algo parecido a lo siguiente debería funcionar:

$(function() { 
    GetResults(); 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 
    for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
    } 
    }); 
} 
2

Dadas sus requisitos actualizados ...

no puedo mover el procesamiento de bucle en la función de devolución de llamada de la solicitud JSON porque estoy reutilizando el funcionalidad de GetResults varios tiempo en toda la página, a menos que I quiera duplicar el código. ¿Algunas ideas?

... GetResults() podría modificar para aceptar una función como un parámetro, que usted entonces ejecutar como su $.getJSON de devolución de llamada (advertencia de código aire):

$(function() { 
    GetResults(function(data) { 
     for(var i = 0; i < data.length; i++) { 
      // Do stuff with data 
     } 
    }); 
}); 

function GetResults(callback) { 
    $.getJSON("/controller/method/", null, callback); 
} 

Como se puede ver de lo general marea de respuestas, es mejor que no intentes luchar contra el modelo de programación jQuery asíncrono.:)

0

puede ordenar una devolución de llamada con los parámetros que deben trabajar muy bien ...

$(function() { 
    GetResults(function(data) { 
     for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
     } 
    }); 

}); 

function GetResults(func) { 
    $.getJSON("/controller/method/", null, func); 
} 
7

me he encontrado algo similar antes. Tendrás que ejecutar la llamada ajax sincrónicamente.

Aquí está mi ejemplo de trabajo:

$.ajax({ 
    type: "POST", 
    url: "/services/GetResources", 
    contentType: "application/json; charset=utf-8", 
    dataType: "json", 
    data: '{resourceFileName:"mapedit",culture:"' + $("#lang-name").val() + '"}', 
    cache: true, 
    async: false, // to set local variable 
    success: function(data) { 
     localizations = data.d; 
    } 
}); 
+0

Esto ciertamente funciona, pero bloquea el hilo de la interfaz de usuario, ¿no es así? (Quizás eso sea aceptable, aunque no parece necesario dada la información que tenemos hasta ahora.) –

+0

Sí, sí bloquea, pero por supuesto solo mientras dure la solicitud. No veo otra forma de evitarlo, dado lo que estás buscando. Bajé por el mismo camino y seguí la ruta de sincronización. – ScottE

Cuestiones relacionadas