简体   繁体   中英

What is the use of ES6 Promise then() fulfillment handler returning a value?

It is said that inside a .then() fulfillment handler, if a value v1 (a non promise object) is returned, then the promise as returned by then() will be a resolved promise, with the resolved value v1 .

But what use is this feature? If we immediately resolve this promise, we may as well write code directly underneath inside this then() fulfillment handler.

Example:

myPromise.then(function(someV) {
  // ...
  return v1;
}).then(function(v) {
  // some code

That is, we may as well move // some code into the first fulfillment handler.

(I thought the usual use case is to return a new Promise() so that we can chain up promises.)

That's a decent question. In other "monadic constructs" there are two functions for this (one for mapping and the other for mapping for a promise) but sometime in 2013 it was decided not to do the same thing in JavaScript and allow returning a value.

This makes sense for chaining an operation with promises without performing an async operation. For example:

fetch('./foo').then(x => x.json()).then(JSON.parse);

The last JSON.parse part has nothing to do with promises or async operations.

There are many cases of promise chains where the first promise handler returns a plain value but cannot be merged easily with the second promise handler in the chain:

  • The intermediate promise is the return value of a function:

     function fn() { return myPromise.then(… => { …; return v1; }); } fn().then(…)
  • The first handler might also throw an exception besides returning a value, in which case the second one should not run but rather the rejection handler:

     myPromise.then(… => { if (…) throw new Error(…); else return v1; }).then(…, err => …);
  • The first handler might also return a promise on other execution path, which needs to be awaited by the second handler:

     myPromise.then(… => { if (…) return fetchSomethingByPromise(); else return v1; }).then(…);
  • There is a rejection handler besides the first handler, whose result the second handler should also get:

     myPromise.then(… => v1, err => v2).then(…);

In all of these cases, the then function will need to deal with plain values. Sure, they always could have been wrapped in Promise.resolve(v1) , but it was decided not to require that. Also there's one more reason why then will need to deal with primitive values: a void handler (eg at the end of the chain) returns undefined , and then will need to handle that appropriately.

I think I understand more about promises to give some insight into this:

Whatever the fulfillment handler returns, primitive value, objects that are not thenables, thenables, real promises, this value will always resolve p , or made into a promise so that it resolves p , where p is what .then() returns.

This is called unwrapping in the promise community, I believe.

So if returning a primitive value or an objects that is not thenable:

this value will be used to resolve p , or it will be made into Promise.resolve(v) which is immediately resolved, and this is to resolve p immediately.

If it is an object that is a thenable, or a real promise:

it can be called as:

obj.then(resolveP) where resolveP is the function that can resolve p .

then the thenable and real promise can both resolve p .

In the promise community, it seems even if it is primitive values or objects that are not thenable, will be made into a promise, so that future operations are more consistent: operation on a promise.

It doesn't matter if you wrap and wrap, because it will just unwrap and unwrap anyway. (when the inner promise resolves, it propagates the unwrapping to the outer wrap, until it cannot continue.)

It almost feels like as if promises are higher level objects that from now on, we only will work with them. (when we are dealing with promises and ordinary values, everything will be converted to a promise (by using Promise.resolve(value) and dealt with).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM