¿Qué son las devoluciones de llamada diferidas?

14

Entiendo la idea de una devolución de llamada, donde paso una función a otra función y esa función utiliza la función suministrada a voluntad.

Estoy luchando para entender las devoluciones de llamadas diferidas, incluso después de googlearlo.

¿Podría alguien proporcionar una explicación simple por favor? Programo en Ruby, pero también conozco un poco C / C ++, pero sobre todo era un programador experimentado en lenguaje ensamblador. Así que me pregunto si es un poco como una pila de direcciones de devolución de llamada que se hacen aparecer. Espero aprender jquery o node.js y estas devoluciones de llamadas diferidas parecen ser parte integral de ambos. Entiendo los principios básicos de subprocesamiento (aunque el objeto mutex me duele la cabeza;)

    
pregunta tentimes 09.04.2012 - 15:36

5 respuestas

3

Por solicitud, aquí hay comentarios presentados como respuesta:

No estoy seguro de que asimile completamente el hecho de que las funciones en JS son objetos de primera clase y, por lo tanto, se pueden almacenar hasta que sean necesarias, más allá del momento en que se crean.

Por ejemplo, supongamos que desea escribir en un archivo y luego imprimir un mensaje de registro; así que llama a la función "escribir ()" (o lo que sea) y pásele una función que emita el mensaje de registro (esta es la función de devolución de llamada diferida). "write ()" almacena internamente una referencia a la función dada, comienza a escribir en el archivo y configura su propia devolución de llamada para saber cuándo finaliza la escritura. Luego regresa antes de que la escritura haya terminado; cuando es así, la devolución de llamada interna se llama de alguna manera (este es el trabajo del marco subyacente, en el caso de node.js, se realiza con un bucle de eventos), que luego llama a su devolución de llamada que imprime el mensaje de registro.

La parte "diferida" simplemente significa que su función de devolución de llamada no se llama de inmediato; llamarlo está aplazado hasta el momento apropiado. En el caso de funciones asíncronas como muchas de las de node.js, la devolución de llamada dada generalmente se llama cuando la operación se completa (o se produce un error).

La mayoría de las cosas son asíncronas en node.js, pero en el navegador, por ejemplo. jQuery, la mayoría de las cosas son en realidad síncronas (excepto, obviamente, para solicitudes AJAX). Dado que las funciones de primera clase son tan útiles en JavaScript (especialmente debido a un gran soporte de cierre), las devoluciones de llamadas también se utilizan en todas partes en el navegador, pero no están "diferidas" para operaciones sincrónicas (excepto en la medida en que no son llamadas de inmediato por usted, pero más tarde por la función que llame).

El hecho de que el sistema subyacente esté controlado por eventos es ortogonal al uso de devoluciones de llamada diferidas; puede imaginar una versión (muy lenta) de node.js que inició un hilo para cada operación, y luego llamó a su llamada devuelta cuando el hilo terminó su trabajo, sin utilizar eventos. Por supuesto, este es un modelo horrible, pero ilustra mi punto :-)

    
respondido por el Cameron 09.04.2012 - 20:09
7

La forma en que funciona una devolución de llamada diferida es que cada vez que se agrega una devolución de llamada, esa devolución de llamada se inserta en una matriz. Luego, cuando se llama al método .resolve() o .resolveWith() en el objeto diferido, todas las devoluciones de llamada .done() en la matriz se ejecutan en orden.

Ahora podemos ver qué es un objeto diferido. Tome el siguiente fragmento como ejemplo.

var deferred = $.Deferred();
var promise = deferred.promise();

Lo que tenemos ahora es un objeto diferido y el objeto promesa del objeto diferido. El objeto Diferido tiene todos los mismos métodos que el objeto promesa, sin embargo, el objeto promesa solo tiene los métodos .done() , .fail() y .always() que se usan para agregar devoluciones de llamada al objeto diferido para cada event respectivo. El objeto diferido, por otro lado, tiene varios otros métodos, lo más importante es .resolve() y .reject() . Cuando se llama a estos métodos en el objeto diferido, se llaman todas las devoluciones de llamada. .resolve() dispara las devoluciones de llamada .done() y .always() , mientras que el método .reject() llama a las devoluciones de llamada .fail() y .always() .

Generalmente, el objeto diferido se mantiene oculto dentro de un ámbito privado, y el objeto de promesa se devuelve desde la función para que se puedan colocar devoluciones de llamada en él. El objeto diferido se resolverá más adelante, como después de completar una solicitud ajax o después de cargar una imagen, después de un setTimeout, etc. También es importante darse cuenta de que un objeto diferido solo se puede resolver una vez. Si ya está resuelto, las devoluciones de llamada se llamarán de inmediato.

Aquí hay otro ejemplo, uno que uso:

function loadImage(url) {
    var def = $.Deferred(),
        img = new Image();
    $(img).on("load error",function(e){
        if (e.type === "error") {
            def.reject(url);
        }
        else {
            def.resolve(url);
        }
    });
    img.src = url;
    // return the promise object so that callbacks can
    // be defined on the deferred object.
    return def.promise();
}
loadImage("foobar.jpg").done(function(){
    alert("The image is loaded!");
}).fail(function(){
    alert("The image failed to load!");
}).always(function(){
    alert("This is always called!");
});

Para obtener más información sobre el método jQuery $.Deferred() y los objetos diferidos, visite enlace

    
respondido por el Kevin B 09.04.2012 - 16:24
3

No estoy seguro, pero creo que una devolución de llamada diferida se refiere a una devolución de llamada asíncrona, por lo que tendrá más suerte en la búsqueda de Google para eso.

La mejor explicación que encontré fue en enlace

  

Oye, probablemente, ExpensiveFunction (), haz lo que quieras, pero yo, el único subproceso Node.js, no voy a esperar aquí hasta que hayas terminado, continuaré ejecutando las líneas de código debajo de ti, así que ¿Por favor toma este CallbackFunction () aquí y llámalo cuando hayas terminado de hacer tus cosas caras? ¡Gracias! "

En este ejemplo, probablyExpensiveFunction es una función no bloqueante (o asíncrona). Esto significa que no se ejecuta de inmediato, sino que se coloca en un llamado bucle de eventos. El subproceso node.js continuará la ejecución, pero en algún momento decidirá ejecutar algo desde el bucle de eventos. Cuando llega a probablemente ExpensiveFunction, lo llama, y cuando probablemente ExpensiveFunction finaliza la ejecución, llama a la devolución de llamada (diferida) pasada como un parámetro para ello.

Como ejemplo de probablemente ExpensiveFunction, puede tomar fs.readFile

    
respondido por el mihai 09.04.2012 - 15:49
3

JavaScript es de un solo hilo, por lo que no puedes pensar en términos de hilos para entender esto. Aquí hay un ejemplo de devoluciones de llamada regulares y asíncronas utilizando jQuery:

var regularCallback = function(evt) {
    alert("I'm a callback!")
}
var asyncCallback = function(data) {
    alert("I only run when an async operation finishes!")
}

// Bind the regular callback to a button's click event
$('#mybutton').on('click', regularCallback);

// Start an ajax request to the server. The request is asynchronous, so code
// below this line will execute immediately. The callback function
// will only be called when the request is complete.
$.get("http://google.com", asyncCallback);
    
respondido por el bfavaretto 09.04.2012 - 16:09
1

Las devoluciones de llamada diferidas (también conocidas como Promices ) le permiten escribir código asíncrono secuencial, sin dolor y espagueti de devolución de llamada:

$.when( doAjax(), doAnotherAjax() ).then( haveFunWithMoreAjax ).then( animateStuff );

'when' te permite esperar a que las funciones regresen en paralelo, y then puede ser encadenado secuencialmente.

una nota: aplazados de jQuery ! = Promices / A , su sintaxis es un poco diferente.

Hay buenos artículos sobre el tema: uno at IEBlog y otra en algún blog aleatorio , a book y un pregunta popular de stackoverflow

    
respondido por el c69 09.04.2012 - 17:05

Lea otras preguntas en las etiquetas