Pregunta

¿Cuáles son las diferencias entre diferidos, promesas y futuros?
¿Existe una teoría generalmente aprobada detrás de estos tres?

¿Fue útil?

Solución

A la luz de la aparente aversión de cómo he intentado responder a la pregunta del OP. La respuesta literal es que una promesa es algo compartido con otros objetos, mientras que un diferido debe mantenerse privado. Principalmente, un diferido (que generalmente se extiende prometido) puede resolverse a sí mismo, mientras que una promesa podría no ser capaz de hacerlo.

Si está interesado en las minucias, examine Promesas/A+.


Hasta donde sé, el propósito general es mejorar la claridad y aflojar el acoplamiento a través de una interfaz estandarizada. Ver Lectura sugerida de @jfriend00:

En lugar de pasar directamente las devoluciones de llamada a las funciones, algo que puede conducir a interfaces estrechamente acopladas, el uso de promesas permite separar las preocupaciones por el código que es sincrónico o asincrónico.

Personalmente, he encontrado diferido especialmente útil cuando se trata de plantillas de EG que están pobladas por solicitudes asíncronas, cargando scripts que tienen redes de dependencias y proporcionan comentarios de los usuarios para formar datos de manera que no sea bloqueante.

De hecho, compare la forma de devolución de llamada pura de hacer algo después de cargar CodeMirror en modo JS de manera asincrónica (disculpas, no he usado jQuery en un tiempo):

/* assume getScript has signature like: function (path, callback, context) 
   and listens to onload && onreadystatechange */
$(function () {
   getScript('path/to/CodeMirror', getJSMode);

   // onreadystate is not reliable for callback args.
   function getJSMode() {
       getScript('path/to/CodeMirror/mode/javascript/javascript.js', 
           ourAwesomeScript);
   };

   function ourAwesomeScript() {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   };
});

A las promesas de la versión formulada (nuevamente, disculpas, no estoy al día en jQuery):

/* Assume getScript returns a promise object */
$(function () {
   $.when(
       getScript('path/to/CodeMirror'),
       getScript('path/to/CodeMirror/mode/javascript/javascript.js')
   ).then(function () {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   });
});

Disculpas por el código semi-pseudo, pero espero que deje la idea central algo clara. Básicamente, al devolver una promesa estandarizada, puede pasar la promesa, lo que permite una agrupación más clara.

Otros consejos

Estas respuestas, incluida la respuesta seleccionada, son buenas para introducir promesas conceptualmente, pero carentes de cuáles son exactamente las diferencias en la terminología que surge al usar bibliotecas que las implementan (y allí allíson diferencias importantes).

Dado que todavía está una especificación en evolución, la respuesta actualmente proviene de intentar encuestar ambas referencias (como Wikipedia) e implementaciones (como jQuery):

  • Diferido: Nunca se describe en referencias populares, 1 2 3 4 pero comúnmente utilizado por las implementaciones como el árbitro de la resolución de la promesa (implementando resolve y reject). 5 6 7

    A veces, los diferidos también son promesas (implementando then), 5 6 Otras veces se considera más puro tener los diferidos solo capaces de resolución, y obligar al usuario a acceder a la promesa de usar then. 7

  • Promesa: La palabra más abarcadora para la estrategia en discusión.

    Un objeto proxy almacena el resultado de una función objetivo cuya sincronicidad nos gustaría abstraer, además de exponer un then Función Aceptar otra función objetivo y devolver una nueva promesa. 2

    Ejemplo de Commonjs:

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44
    

     

    Siempre se describe en referencias populares, aunque nunca se especifica en cuanto a cuya resolución de responsabilidad cae. 1 2 3 4

    Siempre presente en implementaciones populares y nunca se les dio a los abilitos de resolución. 5 6 7

  • Futuro: un término aparentemente desaprobado en algunas referencias populares 1 y al menos una implementación popular, 8 pero aparentemente siendo eliminado por la discusión con preferencia por el término 'promesa' 3 Y no siempre se menciona en las presentaciones populares del tema. 9

    Sin embargo, al menos una biblioteca usa el término genéricamente para abstraer sincronicidad y manejo de errores, sin proporcionar then funcionalidad. 10 No está claro si evitar el término 'promesa' fue intencional, pero probablemente una buena opción ya que las promesas se construyen alrededor de 'thenables'. 2

Referencias

  1. Wikipedia sobre promesas y futuros
  2. Promesas/a+ especificaciones
  3. Dom Standard en promesas
  4. DOM Standard Promises Spec WIP
  5. Dojo Toolkit de diferencias
  6. JQuery Diferreds
  7. Q
  8. FutureJS
  9. Sección funcional de JavaScript en promesas
  10. Futuros en pruebas de integración de AngularJS

Misc potencialmente cosas confusas

Lo que realmente hizo que todo haga clic para mí fue esta presentación por Domenic Denicola.

en un Github Gist, Dio la descripción que más me gusta, es muy conciso:

El objetivo de las promesas es devolvernos la composición funcional y el burbujeo de errores en el mundo asíncrono.

En otra palabra, las promesas son una forma que nos permite escribir asincrónico código que es casi tan fácil de escribir como si fuera sincrónico.

Considere este ejemplo, con promesas:

getTweetsFor("domenic") // promise-returning async function
    .then(function (tweets) {
        var shortUrls = parseTweetsForUrls(tweets);
        var mostRecentShortUrl = shortUrls[0];
        return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
    })
    .then(doHttpRequest) // promise-returning async function
    .then(
        function (responseBody) {
            console.log("Most recent link text:", responseBody);
        },
        function (error) {
            console.error("Error with the twitterverse:", error);
        }
    );

Funciona como si estuvieras escribiendo este código sincrónico:

try {
    var tweets = getTweetsFor("domenic"); // blocking
    var shortUrls = parseTweetsForUrls(tweets);
    var mostRecentShortUrl = shortUrls[0];
    var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
    console.log("Most recent link text:", responseBody);
} catch (error) {
    console.error("Error with the twitterverse: ", error);
}

(Si esto todavía suena complicado, ¡mira esa presentación!)

En cuanto a diferido, es una forma de .resolve() o .reject() promesas. En el Promesas/B especificación, se llama .defer(). En jQuery, es $.Deferred().

Tenga en cuenta que, hasta donde yo sé, la implementación de la promesa en jQuery está rota (ver esa esencia), al menos a partir de jQuery 1.8.2.
Supuestamente implementa Promesas/A entonces, pero no obtienes el manejo correcto de errores que debes, en el sentido de que toda la funcionalidad de "prueba de prueba/captura" no funcionará. Lo cual es una lástima, porque tener un "Try/Catch" con el código Async es completamente genial.

Si va a utilizar promesas (¡debe probarlas con su propio código!), Use Q de Kris Kowal. La versión jQuery es solo un agregador de devolución de llamada para escribir código jQuery limpiador, pero pierde el punto.

Con respecto al futuro, no tengo idea, no lo he visto en ninguna API.

Editar: La charla de YouTube de Domenic Denicola sobre promesas de @GranjaEl comentario a continuación.

Una cita de Michael Jackson (sí, Michael Jackson) del video:

Quiero que quemes esta frase en tu mente: Una promesa es una valor asincrónico.

Esta es una excelente descripción: una promesa es como una variable del futuro: una referencia de primera clase a algo que, en algún momento, existirá (o sucederá).

A Promesa representa un proxy para un valor que no necesariamente se conoce cuando se crea la promesa. Le permite asociar a los manejadores a la eventual valor de éxito o la razón de falla de una acción asíncrona. Esto permite que los métodos asincrónicos devuelvan valores como métodos sincrónicos: en lugar del valor final, el método asincrónico devuelve una promesa de tener un valor en algún momento en el futuro.

https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/promise

los deferred.promise() El método permite que una función asincrónica evite que otro código interfiera con el progreso o el estado de su solicitud interna. La promesa expone solo los métodos diferidos necesarios para unir manejadores adicionales o determinar el estado (Luego, hecho, falla, siempre, tubería, progreso, estado y promesa), pero no los que cambian el estado (Resolver, rechazar, notificar, resolver, rechazar con y notificar con).

Si se proporciona objetivo, deferred.promise() Adjuntará los métodos y luego devolverá este objeto en lugar de crear uno nuevo. Esto puede ser útil para adjuntar el comportamiento de la promesa a un objeto que ya existe.

Si está creando un diferido, mantenga una referencia al diferido para que pueda resolverse o rechazar en algún momento. Devuelva solo el objeto Promise a través de diferido.promise () para que otro código pueda registrar las devoluciones de llamada o inspeccionar el estado actual.

Simplemente podemos decir que un Promesa representa un valor que aún no se conoce donde como un Diferido representa el trabajo que aún no está terminado.


enter image description here

  • A promise representa un valor que aún no se conoce
  • A deferred representa el trabajo que aún no está terminado

Una promesa es un marcador de posición para un resultado que inicialmente se desconoce, mientras que un diferido representa el cálculo que da como resultado el valor.

Referencia

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top