javascript - Hva er forskjellen mellom å returnere en verdi eller Promise.resolve fra then()
Hva er forskjellen mellom:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return "bbb"; // directly returning string
})
.then(function(result) {
console.log(result);
});og dette:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return Promise.resolve("bbb"); // returning a promise
})
.then(function(result) {
console.log(result);
});Jeg spør fordi jeg får forskjellig oppførsel ved bruk av Angular og $http-tjenesten med kjeding av .then(). Litt for mye kode, derfor først eksemplet ovenfor.
Svar #1
Enkelt sagt, inne i en then-håndteringsfunksjon:
A) Når x er en verdi (nummer, streng, osv.):
return xtilsvarerreturn Promise.resolve(x)throw xtilsvarerreturn Promise.reject(x)
B) Når x er et løfte som allerede er fullført (ikke lenger avventende):
- Hvis den oppløste verdien av løftet er
y, erreturn xekvivalent medreturn Promise.resolve(y). - Hvis den avviste verdien av løftet er
y, erreturn xekvivalent medreturn Promise.reject(y).
C) Når x er et Promise som venter:
return xvil returnere et ventende Promise, og det vil bli evaluert på den påfølgendethen.
Les mer om dette emnet på dokumentasjonen for Promise.prototype.then().
Svar #2
Regelen er at hvis funksjonen som er i then-håndtereren returnerer en verdi, blir løftet oppfylt/avvist med den verdien, og hvis funksjonen returnerer et løfte, skjer det at neste then-ledd blir then-leddet til løftet som funksjonen returnerte, så i dette tilfellet følger det første eksemplet den normale rekkefølgen av thens og skriver ut verdier som man kan forvente. I det andre eksemplet, løfteobjektet som blir returnert når du gjør Promise.resolve("bbb"),s then er den then som blir kalt ved kjeding (for alle praktiske formål). Måten det faktisk fungerer på er beskrevet nedenfor i mer detalj.
Siterer fra Promises/A+-spesifikasjonen:
Løfteoppløsningsprosedyren er en abstrakt operasjon som tar som input et løfte og en verdi, som vi betegner som
[[Resolve]](promise, x). Hvisxer et thenable, forsøker den å få løftet til å adoptere tilstanden tilx, under antakelsen om at x oppfører seg i det minste delvis som et løfte. Ellers oppfyller den løftet med verdienx.Denne behandlingen av thenables gjør at promise-implementasjoner kan samhandle, så lenge de eksponerer en Promises/A+-kompatibel then-metode. Den tillater også Promises/A+-implementasjoner å «assimilere» ikke-konforme implementasjoner med rimelige then-metoder.
Det viktigste å legge merke til her er denne linjen:
hvis
xer et løfte, overta tilstanden dens [3.4]lenke: https://promisesaplus.com/#point-49
Svar #3
Begge eksemplene dine bør oppføre seg ganske likt.
En verdi returnert inne i en then()-handler blir oppløsningsverdien til løftet som returneres fra den then(). Hvis verdien som returneres inne i .then er et løfte, vil løftet som returneres av then() "adoptere tilstanden" til det løftet og løse/avvise på samme måte som det returnerte løftet gjør.
I ditt første eksempel returnerer du "bbb" i den første then()-håndtereren, så "bbb" blir sendt videre til neste then()-håndterer.
I ditt andre eksempel returnerer du et løfte som umiddelbart blir oppfylt med verdien "bbb", så "bbb" blir sendt videre til neste then()-håndterer. (Promise.resolve() her er overflødig).
Resultatet er det samme.
Hvis du kan vise oss et eksempel som faktisk viser forskjellig atferd, kan vi fortelle deg hvorfor det skjer.
Svar #4
Du har allerede fått et godt formelt svar. Jeg tenkte jeg skulle legge til et kort et.
Følgende ting er identiske med Promises/A+-løfter:
- Å kalle
Promise.resolve(I ditt Angular-tilfelle er det$q.when) - Kalle på løfte-konstruktøren og løse det i dens løser. I ditt tilfelle er det
new $q. - Å returnere en verdi fra en
then-tilbakekallingsfunksjon. - Å kalle Promise.all på en array med en verdi og deretter hente ut den verdien.
Så følgende er alle identiske for et løfte eller en enkel verdi X:
Promise.resolve(x);
new Promise(function(resolve, reject){ resolve(x); });
Promise.resolve().then(function(){ return x; });
Promise.all([x]).then(function(arr){ return arr[0]; });
Og det er ikke overraskende, spesifikasjonen for løfter er basert på Promise Resolution Procedure som muliggjør enkel samhandling mellom biblioteker (som $q og native promises) og gjør livet ditt generelt lettere. Når en løfteoppfyllelse kan oppstå, skjer en oppfyllelse som skaper generell konsistens.
