How do you handle promises that do not resolve?
Example:
class Utils {
static async thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(number: number) {
return new Promise((resolve, reject) => {
if(number === 2) {
resolve('ok')
}
})
}
}
console.log(await Utils.thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(2))
// this will print "ok" because 2 is passed and the promise is resolved
console.log(await Utils.thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(5))
// this will crash the program silently
uncaughtException
and unhandledRejection
return nothing when the promise is unresolved. Adding a try/catch
around the await doesn't work (no errors). Finally, the only thing that works is using Promise.then
instead of await
.
Problem is the code base is riddled with async/await
and Promises that sometimes resolve (depending on conditions)
Question: Is there a typescript flag I can add to detect a missing resolve/reject? or maybe an automated way to transpile all the async/await
to use Promise.then
?
When using a debugger, the program stops after the Promise and it is difficult to find which function/promise has a missing resolve/reject.
Rewriting all the async/await
calls to use Promise.then
is my last resort.
If you have promises that occasionally don't resolve or reject and that's not the way they are supposed to work (which it usually isn't), then you just have to fix that. There really is no work-around. The proper fix is to get down to the lowest level and fix the code so it reliably resolves or rejects every time.
This is not the proper fix, but implementing a timeout wrapper could help with debugging giving you a log message with some semblance of a stack trace for a timed out promise:
function rejectT(t) {
// create potential error here for better opportunity at stack trace
let e = new Error("Promise timed out");
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(e);
reject(e);
}, t);
});
}
function timeout(p, t = 5000) {
return Promise.race([p, rejectT(t)]);
}
You can then wrap any promise such that instead of:
fn().then(...).catch(...)
You can use:
timeout(fn()).then(...).catch(...);
Or, if you want to set a custom timeout value:
timeout(fn(), 1000).then(...).catch(...);
Again, this is debugging code to help find the culprits that need fixing and to help test fixes, not to bandaid your code.
Rewriting all the async/await calls to use Promise.then is my last resort.
I don't see how this is going to help at all. If await
never finishes, neither will promise.then()
. They are exactly the same in that regard. If the promise never resolves or rejects, then the .then()
handler will never get called either.
Problem is the code base is riddled with async/await and Promises that sometimes resolve (depending on conditions)
There's no shortcut here other than methodical code review to find suspect code that has code paths that may never resolve or reject and then building unit tests to test every function that returns a promise in a variety of conditions.
One likely source of code that never resolves or rejects are some of the promise anti-patterns. The precise reason some of them are anti-patterns is because they can be very easy to mess up. Here are a few references that might spike your sensitivity to suspect code:
Promise Anti-Patterns
Common Promise Anti-Patterns and How to Avoid Them
ES6 Promises: Patterns and Anti-Patterns
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With