The simplest change is to just return the inner promises. That will cause their rejections to propagate upwards to the single .catch(), like this:
function1().then(() => {
return function2().then(() => {
return function3().then(() => {
})
})
}).catch((err) => {
console.log(err);
})
But, this successive nesting of promises is less-than-ideal (some would call it an anti-pattern). If you really want things sequenced these days and you're using a modern JS environment, then you would sequence things and catch errors in one place with await:
async someFunction() {
try {
let val1 = await function1();
let val2 = await function2();
let val3 = await function3();
} catch(e) {
// catch any rejections from the above three `await` statements here
console.log(e);
}
}
Using await also makes it a lot easier to see the code flow and to gather results from multiple asynchronous calls in one scope.
Without await, you could also flatten your original code:
function1().then(() => {
return function2().then(() => {
})
}).then(() => {
return function3().then(() => {
})
}).catch((err) => {
console.log(err);
})
But, most people will consider the await implementation to be simpler.
function1because the other two aren't part of the same promise chain. Minimal example:Promise.resolve().then(() => { Promise.reject("whoops!") }).catch((err) => console.log(err));Promise.resolve().then(() => Promise.reject("whoops!")).catch((err) => console.log(err));function1().then(function2).then(function3).then(() => { /* do whatever */ }).catch(console.log);Promise.resolve().then(function1).then(function2).then(function3).then(() => { /* do whatever */ }).catch(console.log);