Errors thrown in an Async#map don't always become Rejected
See original GitHub issueDescribe the bug
If an error is thrown in an Async#map
, it doesn’t always become a Rejected
.
To Reproduce
const { Async } = require('crocks')
Async((rej, res) => res('a'))
.map(() => { throw new Error('bad') })
.fork(err => console.error({ err }), val => console.log({ val }))
Expected behavior
I would expect an object shaped like { err }
to be logged to console.error
, but instead the error is thrown and logged by itself, and neither of the forked functions are called.
Additional context If you wrap a Promise instead, it works as expected:
Async.fromPromise(() => Promise.resolve('a'))('b')
.map(() => { throw new Error('bad') })
.fork(err => console.error({ err }), val => console.log({ val }))
Issue Analytics
- State:
- Created 4 years ago
- Comments:12 (4 by maintainers)
Top Results From Across the Web
How to Throw Errors From Async Functions in JavaScript?
Async functions and async methods always return a Promise, either resolved or rejected. You must attach then() and catch() , no matter what....
Read more >How to avoid uncaught async errors in Javascript
In this article, you'll learn about a few cases where async exceptions bubble up and become uncaught errors. You'll learn why they happen ......
Read more >Handling Errors (Rejections) in async/await inside Array#map
So in function b I try to get some async data (from a database). It fails and throws an Uncaught Promise Rejection. How...
Read more >async - Documentation - GitHub Pages
async.map ... The same as reject but runs a maximum of limit async operations at a time. ... Results are always returned; however,...
Read more >Writing Promise-Using Specifications - W3C
... always return promises; 4.1.2 Rejection reasons must be Error ... not found: for example asyncMap.get("key") should return a promise for ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
My apologies. I took the bait and wandered into opinion territory, and now we’re off topic. I’ll wander back.
The issue at hand is this:
Promise
into anAsync
viaAsync.fromPromise
, then errors thrown in a.map()
are caught and converted to aRejected
.Async
with the regular factory function, errors thrown in a.map()
are not caught.I find this mismatch in behaviour to be unexpected. Am I incorrect in feeling this way? If this should be expected behaviour, I guess at the very least I would want it documented to try and avoid surprises.
@flintinatux I think you hit the nail on the head with the
fromPromise
function. I think this may be where the issue lies. So no matter what, this behavior will need to stay in place or it will invalidate Async as a Functor and all Natural transformations from other Sum Types also become invalid. Not to mention any Functor Compositions (Nested Functors is a way to view these)So the reason it has to work this way is because in the Category of (gotta squint a little and ignore some bottoms) Javascript Types and Functions, Promises were created with this Error Handling in place. In order to provide a valid Functor, it MUST behave the same way in its source category when we get Async involved.
The issue is that we do not know the behavior when dealing with a Promise at the head or “chain”-ed in. Sometime it will throw, sometime it will not, depending on if
fromPromise
created the Async or not.So the user of a
crocks
Async could alway treat it as it could blow andchain(tryCatch(fn))
one could never use map again without making sure it was also caught somehow, but I see how that may not be intuitive for the beginning/casual user.Another option would be to somehow (don’t know how yet, maybe with how the type is logged) signal to the user that a promise is in the mix.
But no matter where we go, I agree to start we need good documentation around the what and why of this behavior.