2009-05-30 8 views
8

Si tengo una llamada ajax de recuperación (con una devolución de llamada) y luego algún otro código que se ejecuta mientras tanto. ¿Cómo puedo tener una tercera función que se invocará cuando se realicen los dos primeros? Estoy seguro de que es fácil con las encuestas (setTimeout y luego verifico algunas variables) pero prefiero una devolución de llamada.Unir 2 'hilos' en javascript

¿Es posible?

Respuesta

14

Se podía dar la misma devolución de llamada tanto a su llamada AJAX y su otro código que se ejecuta en el ínterin, usar una variable para realizar un seguimiento de su progreso combinado, luego enlazarlas a una devolución de llamada, como a continuación:

// Each time you start a call, increment this by one 
var counter = 0; 

var callback = function() { 
    counter--; 
    if (counter == 0) { 
     // Execute code you wanted to do once both threads are finished. 
    } 
} 
+0

Dado que no hay una verdadera multi-threading en JS (aún) esto también es seguro hacerlo. – Jabe

+0

El problema aquí es que uno de los "hilos" no está realmente terminado cuando llama a la función de devolución de llamada() desde su contexto. – Thevs

+0

Thevs: Es exactamente por eso que hay un contador, por lo que solo continúa la ejecución una vez que ambos "hilos" han terminado. Tenga en cuenta que esta no es una respuesta completa, y a propósito; Estoy asumiendo cierta inteligencia por parte del solicitante, de modo que puedan llenar los vacíos que crean necesarios. Solo intento proporcionar la idea básica de cómo resolver este problema. –

4

La solución de Daniel es la correcta. La tomé y añadí un poco de código extra por lo que no tiene que pensar demasiado;)

function createNotifier() { 
    var counter = 2; 
    return function() { 
     if (--counter == 0) { 
      // do stuff 
     } 
    }; 
} 

var notify = createNotifier(); 
var later = function() { 
    var done = false; 
    // do stuff and set done to true if you're done 
    if (done) { 
     notify(); 
    } 
}; 

function doAjaxCall(notify) { 
    var ajaxCallback = function() { 
     // Respond to the AJAX callback here 
     // Notify that the Ajax callback is done 
     notify(); 
    }; 
    // Here you perform the AJAX call action 
} 

setInterval(later, 200); 
doAjaxCall(notify); 
0

Algo como esto (esquemática):

registerThread() { 
    counter++; 
} 

unregisterThread() { 
    if (--counter == 0) fireEvent('some_user_event'); 
} 

eventHandler_for_some_user_event() { 
    do_stuff(); 
} 
3

El mejor enfoque para esto es tomar ventaja del hecho de que las funciones son objetos de primer orden en JavaScript. Por lo tanto, puede asignarlos a variables e invocarlos a través de la variable, cambiando la función a la que hace referencia la variable según sea necesario.

Por ejemplo:

function firstCallback() { 
    // the first thing has happened 
    // so when the next thing happens, we want to do stuff 
    callback = secondCallback; 
} 

function secondCallback() { 
    // do stuff now both things have happened 
} 

var callback = firstCallback; 

Si los dos trozos de código utilizan ahora la variable de llamar a la función:

callback(); 

entonces lo que uno ejecuta primero llamará al firstCallback, que cambia la variable para apuntar a secondCallback, y así será invocado por el que ejecute el segundo.

Sin embargo, su fraseo de la pregunta implica que todo esto puede ser innecesario, ya que parece que está haciendo una solicitud de Ajax y luego continúa procesando. Como los intérpretes de JavaScript son de subproceso único, la devolución de llamada de Ajax nunca se ejecutará hasta que el cuerpo principal del código que realizó la solicitud haya terminado de ejecutarse de todos modos, incluso si eso es mucho después de que se haya recibido la respuesta.

En caso de que no sea su situación, he creado un working example on my site; ver la fuente para ver el código (justo antes de la etiqueta </body >). Hace una solicitud que el servidor demora por unos segundos, luego una solicitud que recibe una respuesta inmediata. La segunda respuesta de solicitud es manejada por una función, y la respuesta de la primera solicitud es manejada posteriormente por una función diferente, ya que la solicitud que recibió una respuesta primero ha cambiado la variable de devolución de llamada para referirse a la segunda función.

+0

¿Qué pasa con la carrera para ingresar a FirstCallback desde dos hilos? –

0

Usted puede hacer esto fácilmente con Google de Closure library, específicamente goog.async.Deferred:

// Deferred is a container for an incomplete computation. 
var ajaxFinished = goog.async.Deferred(); 

// ajaxCall is the asynchronous function we're calling. 
ajaxCall(//args..., 
    function() { // callback 
     // Process the results... 
     ajaxFinished.callback(); // Signal completion 
    } 
); 

// Do other stuff... 

// Wait for the callback completion before proceeding 
goog.async.when(ajaxFinished, function() { 
    // Do the rest of the stuff... 
}); 

Usted puede unirse a múltiples cálculos asíncronos utilizando awaitDeferred, chainDeferred o goog.async.DeferredList.

3

Usted está hablando de algo llamado diferido en javascript como @Chris Conway mencionado anteriormente. Del mismo modo jQuery también tiene diferido desde v1.5.

comprobar estos Deferred.when() o deferred.done()

No se olvide de comprobar jQuery doc.

Pero para que tenga una idea aquí, es lo que estoy copiando de ese sitio.

$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){ 
    /* a1 and a2 are arguments resolved for the 
     page1 and page2 ajax requests, respectively */ 
    var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */ 
    if (/Whip It/.test(jqXHR.responseText)) { 
     alert("First page has 'Whip It' somewhere."); 
    } 
}); 

// Usando deferred.then()

$.when($.ajax("/page1.php"), $.ajax("/page2.php")) 
.then(myFunc, myFailure); 
+0

El código en su ejemplo es un poco complicado pero es una buena solución. –

+0

Para una mayor experimentación, encontré este tutorial como uno bueno [diferido, promesa, pipe] (http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/) –