Qual é a diferença entre:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return "bbb";
})
.then(function(result) {
console.log(result);
});
e isto:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return Promise.resolve("bbb");
})
.then(function(result) {
console.log(result);
});
Estou perguntando como estou obtendo um comportamento diferente usando o serviço Angular e $ http com encadeamento .then (). Um pouco de código, portanto, primeiro o exemplo acima.
javascript
angularjs
promise
q
spirytus
fonte
fonte
Promise.resolve()
no segundo exemplo é desnecessário.then
manipulador; na verdade, é um aspecto essencial das especificações de promessas que você pode fazer.then
s arbitrariamente aninhados - o termo 'outras línguas' para isso é quethen
é amap
e aflatMap
.new Promise((res, rej) => { return fetch('//google.com').then(() => { return "haha"; }) }).then((result) => alert(result));
esse código será interrompido (não será resolvido para sempre). Mas se eu mudarreturn "haha";
parareturn res("haha");
ele funcionará e alertará "haha". A busca (). Then () já envolveu "haha" em uma promessa resolvida?Respostas:
A regra é que, se a função que está no
then
manipulador retornar um valor, a promessa será resolvida / rejeitada com esse valor e, se a função retornar uma promessa, o que acontece é que a próximathen
cláusula será athen
cláusula da promessa que a função retornou , portanto, neste caso, o primeiro exemplo cai na sequência normal dosthens
valores e imprime comoPromise.resolve("bbb")
seria de esperar, no segundo exemplo, o objeto de promessa que é retornado quando você o faz é othen
que é invocado ao encadear (para todos os efeitos). A maneira como ele realmente funciona é descrita abaixo com mais detalhes.Citando as especificações Promises / A +:
O principal a notar aqui é esta linha:
fonte
then
manipulador retorna uma promessa. +1 para a referência de especificação.[[Resolve]]
ser chamado de capazthen
e de valores, de modo que, essencialmente, envolve um valor com a promessa,return "aaa"
é o mesmo quereturn Promise.resolve("aaa")
ereturn Promise.resolve("aaa")
é o mesmo quereturn Promise.resolve(Promise.resolve("aaa"))
- já que resolver é idempotente chamando-o de um valor mais do que uma vez tem o mesmo resultado."aaa"
ereturn Promise.resolve("aaa")
são permutáveisthen
em todos os casos?Em termos simples, dentro de uma
then
função de manipulador:A) Quando
x
é um valor (número, string, etc):return x
é equivalente areturn Promise.resolve(x)
throw x
é equivalente areturn Promise.reject(x)
B) Quando
x
é uma Promessa que já está liquidada (não está mais pendente):return x
é equivalente areturn Promise.resolve(x)
, se a Promessa já tiver sido resolvida.return x
é equivalente areturn Promise.reject(x)
, se a promessa já foi rejeitada.C) Quando
x
há uma promessa pendente:return x
retornará uma promessa pendente e será avaliada no subsequentethen
.Leia mais sobre este tópico nos documentos Promise.prototype.then () .
fonte
Ambos os seus exemplos devem se comportar da mesma forma.
Um valor retornado dentro de um
then()
manipulador se torna o valor de resolução da promessa retornada a partir delethen()
. Se o valor retornado dentro da.then
promessa for uma promessa, a promessa retornada porthen()
"adotará o estado" dessa promessa e resolverá / rejeitará exatamente como a promessa retornada.No seu primeiro exemplo, você retorna
"bbb"
no primeirothen()
manipulador,"bbb"
sendo passado para o próximothen()
manipulador.No seu segundo exemplo, você retorna uma promessa que é imediatamente resolvida com o valor
"bbb"
,"bbb"
sendo passada para o próximothen()
manipulador. (OPromise.resolve()
aqui é estranho).O resultado é o mesmo.
Se você pode nos mostrar um exemplo que realmente exibe comportamento diferente, podemos dizer por que isso está acontecendo.
fonte
Promise.resolve();
vsreturn;
?undefined
vez de"bbb"
.Você já teve uma boa resposta formal. Eu pensei que deveria adicionar um pequeno.
As seguintes coisas são idênticas às promessas / promessas A + :
Promise.resolve
(no seu caso Angular, isso é$q.when
)new $q
.then
retorno de chamada.Portanto, todos os itens a seguir são idênticos para uma promessa ou valor simples X:
E não é nenhuma surpresa, a especificação de promessas é baseada no Procedimento de resolução de promessas, que permite fácil interoperação entre bibliotecas (como $ q e promessas nativas) e facilita sua vida em geral. Sempre que uma resolução de promessa pode ocorrer, ocorre uma resolução criando consistência geral.
fonte
Promise.resolve().then(function(){ return x; });
? Eu encontrei um snippet fazendo algo semelhante (chamado de função dentro dothen
bloco). Eu pensei que era mais ou menos como fazer um tempo limite, mas é um pouco mais rápido. jsben.ch/HIfDowith
bloco sobre um objeto ou proxy com umx
acessador de propriedade que gera uma exceção. Nesse caso, Promise.resolve (x) causaria um erro gerado, masPromise.resolve().then(function(){ return x; });
seria uma promessa rejeitada, pois o erro é gerado em athen
).if (validator) { Promise.resolve().then(() => { this._cdRef.markForCheck(); }); }
. Aqui a promessa não é atribuída, então qual é o objetivo? Um tempo limite teria (mais ou menos) o mesmo efeito, ou não?A única diferença é que você está criando uma promessa desnecessária
return Promise.resolve("bbb")
. Retornar uma promessa de umonFulfilled()
manipulador inicia a resolução da promessa . É assim que o encadeamento de promessas funciona.fonte