¿Cuáles son las diferencias entre diferidos, promesas y futuros?
¿Existe una teoría generalmente aprobada detrás de estos tres?
¿Cuáles son las diferencias entre diferidos, promesas y futuros?
¿Existe una teoría generalmente aprobada detrás de estos tres?
Respuestas:
A la luz del aparente disgusto por cómo he intentado responder a la pregunta del OP. La respuesta literal es, una promesa es algo compartido con otros objetos, mientras que un diferido debe mantenerse privado. Principalmente, un diferido (que generalmente extiende Promesa) puede resolverse por 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. Vea la 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 síncrono o asíncrono.
Personalmente, he encontrado que diferir es especialmente útil cuando se trata, por ejemplo, de plantillas pobladas por solicitudes asíncronas, cargando scripts que tienen redes de dependencias y proporcionando comentarios de los usuarios para formar datos de manera no bloqueante.
De hecho, compare la forma de devolución de llamada pura de hacer algo después de cargar CodeMirror en modo JS de forma asíncrona (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.");
};
});
Para la versión formulada de promesas (nuevamente, disculpas, no estoy actualizado 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 semi-pseudocódigo, pero espero que aclare la idea central. Básicamente, al devolver una promesa estandarizada, puede pasar la promesa, lo que permite una agrupación más clara.
fn(callback, errback)
no está más estrechamente acoplado o es menos útil que fn().then(callback, errback)
eso, pero esa es una forma incorrecta de usar promesas de todos modos. Especialmente odio el $.when
ejemplo de culto a la carga : no hay absolutamente ninguna razón por la que no pueda tener una $.when
función que funcione con devoluciones de llamada.
Estas respuestas, incluyendo la respuesta seleccionada, son buenos para la introducción de las promesas de vista conceptual, pero carece de detalles de lo que exactamente las diferencias están en la terminología que surge cuando se utilizan las bibliotecas aplicación (y no son diferencias importantes).
Como todavía es una especificación en evolución , la respuesta actualmente proviene de intentar encuestar tanto las referencias (como wikipedia ) como las implementaciones (como jQuery ):
Diferido : nunca descrito en referencias populares,
1 2 3 4
pero comúnmente utilizado por implementaciones como el árbitro de la resolución de promesa (implementación y ).
5 6 7
resolve
reject
A veces, los diferidos también son promesas (implementación then
),
5 6
otras veces se considera más puro tener el diferido solo capaz de resolución, y obligando al usuario a acceder a la promesa de uso .
7 7
then
Promesa : La palabra más completa para la estrategia en discusión.
Un objeto proxy que almacena el resultado de una función objetivo cuya sincronía nos gustaría abstraer, además de exponer una then
función que acepta otra función objetivo y devuelve una nueva promesa.
2
Ejemplo de CommonJS :
> asyncComputeTheAnswerToEverything()
.then(addTwo)
.then(printResult);
44
Siempre se describe en referencias populares, aunque nunca se especifica a qué responsabilidad corresponde la resolución. 1 2 3 4
Siempre presente en implementaciones populares, y nunca con capacidad de resolución. 5 6 7
Futuro : un término aparentemente obsoleto que se encuentra en algunas referencias populares 1 y al menos en una implementación popular, 8 pero que parece estar fuera de discusión con preferencia por el término 'promesa' 3 y no siempre se menciona en introducciones populares al tema. 9 9
Sin embargo, al menos una biblioteca usa el término genéricamente para abstraer la sincronicidad y el manejo de errores, sin proporcionar then
funcionalidad.
10
No está claro si evitar el término "promesa" fue intencional, pero probablemente sea una buena opción, ya que las promesas se basan en los "materiales".
2
Diferencia entre Promesas / A y Promesas / A +
(TL; DR, Promesas / A + resuelve principalmente ambigüedades en Promesas / A)
Task
Lo que realmente hizo que todo fuera clic para mí fue esta presentación de 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 otras palabras, las promesas son una forma que nos permite escribir código asincrónico que es casi tan fácil de escribir como si fuera síncrono .
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 estuviera escribiendo este código síncrono:
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 .resolve()
o .reject()
promesas. En la especificación Promises / B , se llama .defer()
. En jQuery, lo es $.Deferred()
.
Tenga en cuenta que, hasta donde yo sé, la implementación de Promise en jQuery está rota (vea lo esencial), al menos a partir de jQuery 1.8.2.
Supuestamente implementa Promesas / A thenables , pero no obtienes el manejo correcto de errores que deberías, en el sentido de que toda la funcionalidad "async try / catch" no funcionará. Lo cual es una pena, porque tener un "try / catch" con código asíncrono es absolutamente genial.
Si va a usar Promesas (¡debería probarlas con su propio código!), Use la Q de Kris Kowal . La versión de jQuery es solo un agregador de devolución de llamada para escribir código jQuery más limpio, 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 del comentario de @Farm a continuación.
Una cita de Michael Jackson (sí, Michael Jackson ) del video:
Quiero que quemes esta frase en tu mente: una promesa es un 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á).
Una promesa representa un proxy para un valor no necesariamente conocido cuando se crea la promesa. Le permite asociar controladores a un valor de éxito eventual de una acción asincrónica o una razón de falla. Esto permite que los métodos asincrónicos devuelvan valores como los métodos sincrónicos: en lugar del valor final, el método asincrónico promete tener un valor en algún momento en el futuro.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
El deferred.promise()
método permite una función asincrónica para evitar 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 adjuntar controladores adicionales o determinar el estado ( luego, hecho, falla, siempre, canalización, progreso, estado y promesa ), pero no los que cambian el estado ( resolver, rechazar, notificar, resolver con, rechazar con y notificar con ).
Si se proporciona el objetivo, deferred.promise()
adjuntará los métodos en él y luego devolverá este objeto en lugar de crear uno nuevo. Esto puede ser útil para adjuntar el comportamiento Promesa a un objeto que ya existe.
Si está creando un diferido, mantenga una referencia al diferido para que pueda resolverse o rechazarse en algún momento. Devuelva solo el objeto Promise a través de deferred.promise () para que otro código pueda registrar devoluciones de llamada o inspeccionar el estado actual.
Simplemente podemos decir que una Promesa representa un valor que aún no se conoce, mientras que un Diferido representa un trabajo que aún no está terminado.
promise
representa un valor que aún no se conoce deferred
representa el trabajo que aún no está terminadoUna 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