Quais são as diferenças entre diferidos, promessas e futuros?
Existe uma teoria geralmente aprovada por trás de todos esses três?
Quais são as diferenças entre diferidos, promessas e futuros?
Existe uma teoria geralmente aprovada por trás de todos esses três?
Respostas:
À luz da aparente aversão a como tentei responder à pergunta do OP. A resposta literal é que uma promessa é algo compartilhado com outros objetos, enquanto um adiado deve ser mantido em sigilo. Principalmente, um diferido (que geralmente estende a Promessa) pode se resolver, enquanto uma promessa pode não ser capaz de fazê-lo.
Se você estiver interessado nas minúcias, examine Promessas / A + .
Até onde eu sei, o objetivo geral é melhorar a clareza e afrouxar o acoplamento por meio de uma interface padronizada. Veja a leitura sugerida de @ jfriend00:
Em vez de transmitir diretamente retornos de chamada para funções, algo que pode levar a interfaces fortemente acopladas, o uso de promessas permite separar as preocupações com o código que é síncrono ou assíncrono.
Pessoalmente, achei o adiamento especialmente útil ao lidar com, por exemplo, modelos preenchidos por solicitações assíncronas, carregar scripts que possuem redes de dependências e fornecer feedback do usuário para formar dados de maneira não-bloqueadora.
Na verdade, compare a forma pura de retorno de chamada de algo após carregar o CodeMirror no modo JS de forma assíncrona (desculpas, eu não uso o jQuery há algum tempo ):
/* 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 a versão formulada das promessas (novamente, desculpas, não estou atualizado no 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.");
});
});
Desculpas pelo semi-pseudo-código, mas espero que deixe a idéia central um pouco clara. Basicamente, retornando uma promessa padronizada, você pode passá-la, permitindo um agrupamento mais claro.
fn(callback, errback)
não é tão acoplado nem menos útil do que fn().then(callback, errback)
- mas essa é uma maneira errada de usar promessas de qualquer maneira. Eu odeio especialmente o $.when
exemplo do culto à carga - não há absolutamente nenhuma razão para que você não possa ter uma $.when
função que funcione com retornos de chamada.
Estas respostas, incluindo a resposta selecionada, são bons para a introdução de promessas conceitualmente, mas com falta de detalhes do que exatamente são as diferenças na terminologia que surge quando usando bibliotecas a sua aplicação (e não são diferenças importantes).
Como ainda é uma especificação em evolução , atualmente a resposta vem da tentativa de pesquisar tanto as referências (como a wikipedia ) quanto as implementações (como o jQuery ):
Adiado : nunca descrito em referências populares,
1 2 3 4,
mas comumente usado pelas implementações como o árbitro da resolução da promessa (implementação e ).
5 6 7
resolve
reject
Às vezes, adiamentos também são promessas (implementação then
),
5 6
vezes, é mais puro ter o adiado apenas com capacidade de resolução e forçar o usuário a acessar a promessa de uso .
7
then
Promessa : a palavra mais abrangente para a estratégia em discussão.
Um objeto proxy que armazena o resultado de uma função de destino cuja sincronicidade gostaríamos de abstrair, além de expor uma then
função que aceita outra função de destino e retorna uma nova promessa.
2
Exemplo do CommonJS :
> asyncComputeTheAnswerToEverything()
.then(addTwo)
.then(printResult);
44
Sempre descrito em referências populares, embora nunca especificado sobre cuja resolução de responsabilidade se enquadra. 1 2 3 4
Sempre presente em implementações populares e nunca com capacidade de resolução. 5 6 7
Futuro : um termo aparentemente obsoleto encontrado em algumas referências populares 1 e pelo menos em uma implementação popular 8 , mas aparentemente sendo eliminado da discussão em preferência ao termo 'promessa' 3 e nem sempre mencionado nas introduções populares ao tópico. 9
No entanto, pelo menos uma biblioteca usa o termo genericamente para abstrair a sincronicidade e o tratamento de erros, sem fornecer then
funcionalidade.
10
Não está claro se evitar o termo 'promessa' foi intencional, mas provavelmente é uma boa escolha, pois as promessas são construídas em torno de 'partes do mundo'.
2
Diferença entre Promessas / A e Promessas / A +
(TL; DR, Promises / A + resolve principalmente ambiguidades em Promises / A)
Task
O que realmente fez tudo clicar para mim foi esta apresentação de Domenic Denicola.
Em uma essência do github , ele deu a descrição que eu mais gosto, é muito conciso:
O objetivo das promessas é devolver a composição funcional e os erros que ocorrem no mundo assíncrono.
Em outras palavras, as promessas são uma maneira que nos permite escrever código assíncrono que é quase tão fácil de escrever quanto se fosse síncrono .
Considere este exemplo, com promessas:
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 se você estivesse escrevendo 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);
}
(Se isso ainda parecer complicado, assista à apresentação!)
Em relação ao diferido, é um caminho .resolve()
ou .reject()
promessas. Nas especificações Promises / B , é chamado .defer()
. No jQuery, é $.Deferred()
.
Observe que, até onde eu sei, a implementação do Promise no jQuery está quebrada (veja a essência), pelo menos a partir do jQuery 1.8.2.
Ele supostamente implementa as tabelas Promises / A , mas você não recebe o tratamento correto de erros que deveria, no sentido de que toda a funcionalidade "assíncrona try / catch" não funcionará. O que é uma pena, porque ter um "try / catch" com código assíncrono é absolutamente legal.
Se você vai usar o Promises (você deve testá-lo com seu próprio código!), Use o Q de Kris Kowal . A versão do jQuery é apenas um agregador de retorno de chamada para escrever um código jQuery mais limpo, mas perde o objetivo.
Em relação ao futuro, não faço ideia, não vi isso em nenhuma API.
Edit: Domenic Denicola fala no youtube sobre Promessas a partir do comentário de @Farm abaixo.
Uma citação de Michael Jackson (sim, Michael Jackson ) do vídeo:
Quero que você grave esta frase em sua mente: uma promessa é um valor assíncrono .
Esta é uma descrição excelente: uma promessa é como uma variável do futuro - uma referência de primeira classe a algo que, em algum momento, existirá (ou acontecerá).
Uma promessa representa um proxy para um valor não necessariamente conhecido quando a promessa é criada. Ele permite associar manipuladores ao eventual valor de sucesso ou motivo de falha de uma ação assíncrona. Isso permite que métodos assíncronos retornem valores como métodos síncronos: em vez do valor final, o método assíncrono retorna a promessa de ter um valor em algum momento no futuro.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
O deferred.promise()
método permite que uma função assíncrona impeça que outro código interfira no andamento ou status de sua solicitação interna. A Promessa expõe apenas os métodos Adiados necessários para anexar manipuladores adicionais ou determinar o estado ( então, concluído, falhar, sempre, canalizar, progresso, estado e promessa ), mas não aqueles que alteram o estado ( resolver, rejeitar, notificar, resolver com, rejectWith e notifyWith ).
Se o destino for fornecido, deferred.promise()
anexará os métodos a ele e retornará esse objeto em vez de criar um novo. Isso pode ser útil para anexar o comportamento da promessa a um objeto que já existe.
Se você estiver criando um adiado, mantenha uma referência ao adiado para que ele possa ser resolvido ou rejeitado em algum momento. Retorne apenas o objeto Promise via deferred.promise () para que outro código possa registrar retornos de chamada ou inspecionar o estado atual.
Simplesmente, podemos dizer que uma promessa representa um valor que ainda não é conhecido, enquanto que um adiado representa um trabalho que ainda não foi concluído.
promise
representa um valor que ainda não é conhecido deferred
representa um trabalho que ainda não está concluídoUma promessa é um espaço reservado para um resultado que é inicialmente desconhecido enquanto um adiado representa o cálculo que resulta no valor.
Referência