-
Notifications
You must be signed in to change notification settings - Fork 8
Return consistent promise object for repeated calls with the same key #3
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
Conversation
Thanks @anleac for helping out here! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 LGTM
@keithamus should I bump the package version as well? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. I did a bit of red-green testing to make sure that the test fails when with the original code in master
and it checks out on my machine.
I'll leave the final approval to @keithamus
Normally we do that as part of the publishing process after merging the PR. |
This test can be run in isolation and more readily describes the expected pattern of behavior. This simplifies debugging later.
The caught Promise _must_ be allowed to be re-caught to allow for proper rejection handling. This test affirms that.
The earlier test which affirms Promise equality with subsequent calls guarantees the behavior of sequential ordering as per the spec. It is pointless to test this as if the test breaks it is a bug with the JS engine and one we're unlikely able to fix (or is at least out of the scope of this project). Our interest is only in the earlier test of referential equality. This test also tests the cache implementation, but this is needless as there are other tests which affirm these semantics.
I've simplified the test cases to be more explicit about the behaviours we expect:
I think this is good to go now 😉 😄 |
Overview
While using memoize in our code we identified an issue where the order of promise execution got scrambled by the use of memoize.
This PR fixes this issue.
Root cause
The first call to memoize with a certain key returns one promise, all subsequent calls to memoize with the same key return a different promise.
This is because the first call creates a new promise with the
.catch
call and returns it, but caches the original "inner" promise.Following calls to memoize return only the "inner" promise.
Suggested fix
In the case of having a promise object as the result of the evaluated function, cache the complex promise with the
catch
call in it.This way the first and subsequent calls will return the same promise and all will register their events on it.
Details:
We are using memoize to memoize the suggested autocomplete entries for a text input in our web page, they all have the same cache key.
When the user is typing a string into the input, each letter invokes the
onchange
event that uses memoize and awaits the promise that fetches data from the server.What we see is that when the promise returned by the memoized function is resolved, the first caller's
then
method is being invoked last (instead of first as expected).Repro steps:
Expected behavior - the
then
statement from item1
is invoked before thethen
statement of item2
.Note: also see the unit test in this PR to illustrate this scenario. This test is failing in the current
master
branch.