JavaScript Promises tl;dr
A superquick overview of Details about Promises

Search for a command to run...
A superquick overview of Details about Promises

No comments yet. Be the first to comment.
Which platform is better at what, how to connect them and why to use both

On my last post, I got wild comments from the "social" internet community. It went from: "I didn't read it but I disagree" to people telling me I'm just a random guy to randomly (moreso unfoundedly) ranting on Next.js - despite the fact that I broug...
As expected when posting, some users claim that I picked one specific sample. I can't put all samples here that I found, this blog post would be endless. You are very welcome to check the code yourself, with Code Complexity linters and your own thoug...

For any of my projects in the last years, Next.js was the framework of choice. For future projects I'm not sure anymore and I'm in the midst of a Next.js crisis so to say. Please note: I'm not bashing Next.js here. I'm using Next.js still everyday b...

Preamble: This guide is not intended for local / dev installation. Supabase already has a dev setup with the CLI - so use that one. This guide is for actual self-hosting and it's quite some honest work, definitely worth it. If you don't wanna spend a...

Stop the talk, let's start getting into it.
If then or catch return a value that is NOT a promise then it will be wrapped into a new promise and chained and forwarded to the next one. That means starting from a catch you can return a value and .then it.
All of the samples here will output Hello World1
const appendWorld = s => `${s} World`;
const appendOne = s => `${s}1`;
const log = v => console.log(v);
Promise.resolve('Hello').then(appendWorld).then(appendOne).then(log);
Promise.resolve('Hello').then(v => Promise.resolve(appendWorld(v))).then(appendOne).then(log);
Promise.reject('Hello').catch(appendWorld).then(appendOne).then(log);
Promise.resolve('Blogging').then(() => 'Hello').then(appendWorld).then(appendOne).then(log)
finally cannot return a value that can be chained. Kind of implied by it's name. It is called no matter if another .then or .catch was called before. When the Promise was fulfilled in any way then .finally is called. Good for cleanup work.
E.g.
Promise.reject()
.catch(() => console.log('Catch is called'))
.finally((s) => console.log('finally called'))
outputs
Catch is called
finally is called
.catchPromise.resolve()
.then(() => {})
.then(() => { throw new Error('hey') })
.then(() => console.log('i am never called'))
.catch(() => console.log('error'));
.catch statements are usefulPromise.resolve()
.then(() => Promise.reject())
.catch(() => console.log('much rejection'))
.then(() => console.log('i can continue doing stuff'))
.then(() => Promise.reject('another one'))
.catch(() => console.log('catching the second chain'))
async functions are Promise WrappersThe following code statements have the same effect:
// async
async function foobar() {
return 'foo';
}
// non-async
function foobar() {
return Promise.resolve('foo');
}
awaiting promises must be done carefullyIf you await a promise then you need to be careful when checking for "success" because errors can be hidden.
See the following example:
const foobar = await Promise.reject(new Error('error thrown')).catch(error => error);
if (foobar) {
// This does not imply success ⚠️👩🚀
} else {
// This does not imply an error case
}
The problem is that the provided promise is properly caught. Referring back to promise-chaining now the result of the catch statement can be chained, hence new Error... is the resulting object if you'd call .then on it. And that is simply the same as calling await on it. So here foobar contains new Error... which is an object which when checking for if(foobar) returns true although an error was thrown. So you need to be aware of what your promises return.
Promise.race and Promise.anyBoth race and any complete with the Promise whichever is first. But there is a big difference: race finishes with the first Promise to EITHER resolve OR reject whilst any finishes only with the first actually resolved Promise.
In this Promise.race sample the error Promise wins because it is first:
const promise1 = new Promise((resolve, reject) => setTimeout(reject, 100));
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 300));
Promise
.race([promise1, promise2])
.then(v => console.log('resolved', v))
.catch(v => console.log('error', v));
In this Promise.any sample the resolved Promise wins because it is the first to actually resolve:
const promise1 = new Promise((resolve, reject) => setTimeout(reject, 100));
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 300));
Promise
.any([promise1, promise2])
.then(v => console.log('resolved', v))
.catch(v => console.log('error', v));
This one is pretty intuitive: It either resolves when ALL promises are resolved OR it rejects when one of the promises is rejected.
// outputs ['one', 'two']
Promise.all([Promise.resolve('one'), Promise.resolve('two')])
.then((resultArray) => console.log(resultArray))
// outputs 'error'
Promise.all([Promise.resolve('one'), Promise.resolve('two'), Promise.reject()])
.then((resultArray) => console.log(resultArray))
.catch(() => console.log('error'))