- A kind of Monad
A
Promise
is an JavaScript Object representing the eventual completion or failure of an asynchronous operation.
Promises are about making asynchronous code retain most of the lost properties of synchronous code such as flat indentation and one exception channel.
A promise is commonly defined as a proxy for a value that will eventually become available.
Promise Executor
Set the state and return the value.
A Promise executor should call only one resolve
or one reject
. Once one state is changed (pending => fulfilled or pending => rejected)
, that’s all. Any further calls to resolve
or reject
will be ignored.
The executor runs automatically and attempts to perform a job. When it is finished with the attempt, it calls resolve
if it was successful or reject
if there was an error.
The promise
object returned by the new Promise
constructor has these internal properties:
state
— initially"pending"
, then changes to either"fulfilled"
whenresolve
is called or"rejected"
whenreject
is called.result
— initiallyundefined
, then changes tovalue
whenresolve(value)
is called orerror
whenreject(error)
is called.
Promise Consumer
Deal with the value or value.
The constructor function takes a function as an argument. This function is called the executor/consumer function
.
.then
The first argument of .then
is a function that runs when the promise is resolved and receives the result.
The second argument of .then
is a function that runs when the promise is rejected and receives the error.
If we’re interested only in successful completions, then we can provide only one function argument to .then
:
.catch
If we’re interested only in errors, then we can use null
as the first argument: .then(null, errorHandlingFunction)
. Or we can use .catch(errorHandlingFunction)
, which is exactly the same:
The call .catch(f)
is a complete analog of .then(null, f)
, it’s just a shorthand.
.finally
The idea of finally
is to set up a handler for performing cleanup/finalizing after the previous operations are complete.
- A
finally
handler has no arguments. Infinally
we don’t know whether the promise is successful or not. That’s all right, as our task is usually to perform “general” finalizing procedures. - A
finally
handler “passes through” the result or error to the next suitable handler. - A
finally
handler also shouldn’t return anything. If it does, the returned value is silently ignored.
The only exception to this rule is when afinally
handler throws an error. Then this error goes to the next handler, instead of any previous outcome.
finally
is not meant to process a promise result. As said, it’s a place to do generic cleanup, no matter what the outcome was.
Promises Chaining
Returning Promises
Methods
Promise.catch()
If we throw an Error like new Error("Something wrong!")
instead of calling the reject
from the promise executor and handlers, it will still be treated as a rejection. It means that this will be caught by the .catch
handler method.
The catch()
method returns a Promise
and deals with rejected cases only. It behaves the same as calling Promise.prototype.then(undefined, onRejected)
(in fact, calling obj.catch(onRejected)
internally calls obj.then(undefined, onRejected)
).
This means that you have to provide an onRejected
function even if you want to fall back to an undefined
result value - for example obj.catch(() => {})
.
Promise.prototype.finally()
The finally()
method of a Promise
schedules a function, the callback function, to be called when the promise is settled. Like then()
and catch()
, it immediately returns an equivalent Promise
object, allowing you to chain calls to another promise method, an operation called composition.
Promise.resolve()
Promise.resolve() - JavaScript | MDN
The Promise.resolve()
method “resolves” a given value to a Promise
. If the value is a promise, that promise is returned; if the value is a thenable, Promise.resolve()
will call the then()
method with two callbacks it prepared; otherwise the returned promise will be fulfilled with the value.
Promise.all()
Promise.all() - JavaScript | MDN
The Promise.all()
method takes an iterable of promises as an input, and returns a single Promise
that resolves to an array of the results of the input promises. This returned promise will fulfil when all of the input’s promises have fulfilled, or if the input iterable contains no promises. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.
It is done when any one of the promises is settled.
- Example with promises array
Promise.all()
will just pass through non-promises, so using undefined is safe. This will scale better to any set of dependencies.
Promise.allSettled()
The Promise.allSettled()
method returns a promise that fulfills after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.
It is typically used when you have multiple asynchronous tasks that are not dependent on one another to complete successfully, or you’d always like to know the result of each promise.
In comparison, the Promise returned by Promise.all()
may be more appropriate if the tasks are dependent on each other / if you’d like to immediately reject upon any of them rejecting.