I heard that promises are supposed to be linear in code in opposed to callbacks ("callback hell").
Though I still have a scenario similar to callback hell and hoping promises can make their promise and have a linear syntax equivalent to this problem code.
Given promises p()
, q()
,w()
consider this code:
p().then(() => {
q().then(() => {
w().then(() => {
// do something
})
})
})
Can we make an equivalent code which is not indented for every nested promise?
I heard that promises are supposed to be linear in code in opposed to callbacks ("callback hell").
Though I still have a scenario similar to callback hell and hoping promises can make their promise and have a linear syntax equivalent to this problem code.
Given promises p()
, q()
,w()
consider this code:
p().then(() => {
q().then(() => {
w().then(() => {
// do something
})
})
})
Can we make an equivalent code which is not indented for every nested promise?
Share Improve this question edited Dec 30, 2020 at 23:26 asked Dec 30, 2020 at 23:00 user12421682user12421682 1-
If the subsequent promises rely on the preceding promises, they have to indent. Otherwise look into using
async/await
to change your styling. – Taplar Commented Dec 30, 2020 at 23:03
3 Answers
Reset to default 8You should not nest the .then()
handlers but let each .then()
create and return a new Promise
. This is how it was designed to work, otherwise you are still in the callback hell, now the version with promises. No big difference.
The code should be like this:
p()
.then(() => {
return q();
})
.then(() => {
return w();
})
.then(() => {
// do something
});
If all that the .then()
handlers do is to call the next function you can write it in a simpler form (read about arrow functions):
p()
.then(() => q())
.then(() => w())
.then(() => {
// do something
});
Even more, if q
and w
are called without arguments, the code could be as simple as:
p()
.then(q)
.then(w)
.then(() => {
// do something
});
Or you can go the extra mile and instead of using .then()
and .catch()
you use await
. The code bees even more clear and easy to read:
try {
await p();
await q();
await w();
// do something
} catch (err) {
// write here the code you would write in the handler you pass to `.catch()
// in the approach that uses Promises
}
Remarks
If the code above, using await
, is used in a function then that function must be an async
function (just put async
in front of its definition).
The code that uses await
may or may not be used outside of a function (i.e. at module's top level) depending on the runtime you use to run it (browser, Node.js etc).
As another user mentioned, you could use async/await
but another option is just to slightly restructure what you have. Here are some examples of what could work – depending on where and when you need certain pieces of data:
p()
.then(q)
.then(w)
// OR
p()
.then(() => q())
.then(() => w())
Obviously this gets a little more plicated if w()
needs data from both p()
and q()
but that's the gist of it.
You could try using async/await
, which leaves a more cleaner code. It would be like this:
(async () => {
try {
await p();
await q();
await w();
} catch (e) {
// handle error
}
})()
If there is no dependency between each promise you can use await Promise.all
in order to do "all or nothing". In any other case, you can store the returned value and pass it to the next function in order to be used if needed.