Personally, I would just use async / await syntax. This allows for simpler control of waits and resolve / reject values.
const myAsyncFun = async () => { try { await promise1() await promise2 await promise3 return { result: "xyz" } } catch (error) { try { await cleanup() } catch (cleanupError) { // handle cleanup error } finally { throw error // reject with the original error } } }
Original answer below...
Sounds like you want to use Promise.prototype.finally()
When the promise is settled, i.e either fulfilled or rejected, the specified callback function is executed
.catch(error => cleanup() .catch(cleanupErr => { // handle cleanup error here }) .finally(() => Promise.reject(error)) )
This will ensure that the result is a rejected promise (rejecting with error) whether cleanup() resolves or not.
Demo
const cleanup = (fail) => !fail ? Promise.resolve("cleanup good") : Promise.reject("cleanup bad") const go = (failMain, failCleanup) => { const p = !failMain ? Promise.resolve("main good") : Promise.reject("main bad") return p.then(() => ({ result: "xyz" })) .catch(error => cleanup(failCleanup) .catch(cleanupErr => { // handle cleanup error here console.warn(cleanupErr) }) .finally(() => Promise.reject(error)) ) } (async () => { console.info("No errors") await go(false, false).then(console.log, console.error) console.info("Main error only") await go(true, false).then(console.log, console.error) console.info("Main and cleanup errors") await go(true, true).then(console.log, console.error) })()
cleanupfunction that rejects and play around with it..catchto the chain on cleanup?