-
-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Preserve rejection state when using a .then reject handler #59
Conversation
@Kovensky I don't think we should do that. Returned promise is not consumed anywhere, and if one relies on implementation that notifies about unhandled errors, then it'll have its console polutted with tons of "Unhandled error .." reports. |
@medikoo It seems I misunderstood the design of this function, so this PR was indeed incorrect (it seems to convert async functions into sync functions?), but I also think you are misunderstanding what In the case of Also, in your If the memoized function does return a Promise when called, but memoizee doesn't / can't modify the return value, then you can just use I am not sure on the overall architecture of /* Only need one storage -- why store resolved values, it can just return the same Promise that can be forked however many times the caller needs. Settled Promises just call any */
handMemoizedAsyncOp.cache = new Map() // or WeakMap, if arg is object
// any -> Promise<any>
function handMemoizedAsyncOp (arg) {
const memoized = handMemoizedAsyncOp.cache.get(arg)
if (memoized != null) {
// it's a Promise that is either not settled yet, or is resolved
return memoized
}
/* The memoizer doesn't care what happens on success -- it will be correctly cached as a promise resolved by It only has to handle rejection, deleting itself from the cache; future callers will thus not see a cached promise and will make a new request instead. Re-throw the rejection value to ensure that the rejection can be observed (and caught) by anyone that received a copy of this Promise. Not rethrowing will not only prevent caller-attached Note that */
const aPromise =
asyncOp(arg)
.catch(e => { handMemoizedAsyncOp.cache.delete(arg); throw e })
// store a Promise that knows to remove itself on rejection
handMemoizedAsyncOp.cache.set(arg, aPromise)
// return the cached Promise
return aPromise
} All this, of course, depends on a Promises/A+ compliant implementation. If it's not Promises/A+, I have no idea :D |
Yes, it's totally intended and does no harm, see this code comment: https://github.com/medikoo/memoizee/blob/master/ext/promise.js#L39 Now concerning issues related to specific implementations:
As an additional note: It would be too invasive if memoizee will return different promise object than one returned by original function. I'm sure for many it would be totally unexpected. Therefore we cannot chain promise for our internal needs, re-throw eventual error, and return its result |
@medikoo v8 will probably have I didn't even know Bluebird had a Thinking more about it, with the restriction that you can't modify the returned Promise, the branch that you linked is actually the only correct branch, regardless of Node REPL session with native Promise:
Node REPL session with Bluebird Promise:
Crashes with a Fatal error (process.abort()) as you call Again using Bluebird, but with
When the promise is not used, there are two unhandled rejection errors: one on the Promise you create with When the promise is used, I added another end to the chain that doesn't handle it, so now I get 3 rejection errors. When the promise has a Remember, you are never "attaching handlers" to a Promise, you are always constructing new Promises that merely depend on the previous Promise. This incorrect behaviour is not unique when using Bluebird; it will also happen when using any other Promises/A+ implementation that has a
|
Yes, probably at some point, but that's not really relevant to this discussion
That's indeed the thing I've overseen when trying |
I've published update as v0.4.1, and I've also opened issue to introduce solution you suggested as one of the options -> #60 |
With bluebird one can use http://bluebirdjs.com/docs/api/reflect.html in order to find the resolved value without side effects. |
@Rush I would like not to dive into library specific API's, as there are tens of promise libraries out there. |
On any Promises/A+ implementation, throwing in the reject handler will propagate the rejection.