Some great Promise tips here! I've certainly raised my eyebrows at long Promise chains, also kudos for util.promisify. On one of your tips,
The solution, then, is simple: always attach a Promise#catch handler for promises that may reject, no matter how unlikely.
I've been told this as well, but in practice it's just a bit cumbersome to uphold this principle. I mean, wouldn't every Promise have the possibility to reject? You may end up with .catch handlers everywhere, and you would have to define behavior for every catch handler, even those unlikely to reject. It makes testing a whole world of pain. What works best for me (and continues to work for me) is to ensure Promises rejections are being handled correctly everywhere so that all rejections are bubbled up (no more uncaught Promise rejection). All rejections would then exit your code; if this behavior is ever undesirable, those are the points you should write error handling code.
That is definitely a more practical approach. Personally, I've recently found Rust's error handling idioms more elegant than that of JavaScript promises. They have this notion of a Result type that I really like. I'll be writing about it in the near future, where I'll advocate for its usage with JavaScript promises.
Regarding the part you quoted, I would like to add that I was careful to say "may reject" since there are some promises that cannot possibly reject. For example, it is unreasonable to attach a catch handler for Promise.resolve. Something along those lines.
Found rust docs on error handling. The thing is, I like exceptions, and I like that all errors thrown in JavaScript behave pretty much like panic!. Rust provides language semantics to differentiate between recoverable errors (Result) and unrecoverable errors (panic!). However, I don't really see how this is better than throwing errors. Perhaps try/catch blocks are clunky? I should mention that I'm neck deep in functional JavaScript and I don't even use try catch blocks, just tryCatch. <- catches synchronous errors and rejected Promises, also disclaimer that I wrote that function
On "may reject", I think I was triggered by the "always", but touche!
Some great Promise tips here! I've certainly raised my eyebrows at long Promise chains, also kudos for util.promisify. On one of your tips,
I've been told this as well, but in practice it's just a bit cumbersome to uphold this principle. I mean, wouldn't every Promise have the possibility to reject? You may end up with .catch handlers everywhere, and you would have to define behavior for every catch handler, even those unlikely to reject. It makes testing a whole world of pain. What works best for me (and continues to work for me) is to ensure Promises rejections are being handled correctly everywhere so that all rejections are bubbled up (no more uncaught Promise rejection). All rejections would then exit your code; if this behavior is ever undesirable, those are the points you should write error handling code.
That is definitely a more practical approach. Personally, I've recently found Rust's error handling idioms more elegant than that of JavaScript promises. They have this notion of a
Result
type that I really like. I'll be writing about it in the near future, where I'll advocate for its usage with JavaScript promises.Regarding the part you quoted, I would like to add that I was careful to say "may reject" since there are some promises that cannot possibly reject. For example, it is unreasonable to attach a
catch
handler forPromise.resolve
. Something along those lines.Found rust docs on error handling. The thing is, I like exceptions, and I like that all errors thrown in JavaScript behave pretty much like panic!. Rust provides language semantics to differentiate between recoverable errors (Result) and unrecoverable errors (panic!). However, I don't really see how this is better than throwing errors. Perhaps try/catch blocks are clunky? I should mention that I'm neck deep in functional JavaScript and I don't even use try catch blocks, just tryCatch. <- catches synchronous errors and rejected Promises, also disclaimer that I wrote that function
On "may reject", I think I was triggered by the "always", but touche!
Yup, I was coming from the mindset that
try
/catch
blocks are kinda "clunky", which is why I stylistically preferred Rust's error handling.Wise decision. The functional style is indeed beautiful. I never liked
try
/catch
blocks anyway. 😂