-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Data: Return result of middleware chain in resolvers cache middleware #14711
Conversation
The previous bug was hiding another bug, which was that we would return the result of As best I can tell, this was never expected, and never occurred, but only because of how the resolvers cache middleware would drop the result. I suppose an additional testing step is to verify both in this branch and a stable WordPress release that entering the following in your console produces a value of wp.data.dispatch( 'core/editor' ).editPost( { title: 'Hello world' } ); |
So currently, if an action is a generator action, a promise is returned. Currently, in a plugin I write I take advantage of that behaviour to not only await the completion of the dispatch but also return a value from the action generator useful for chaining additional dispatches. With this change will this behaviour break? |
As far as I'm aware, it was never an intended behavior to support. In fact, tests would previously forbid this, or at least for certain types of actions from the That's unfortunate to hear there's some potential compatibility issue here. It'll require some more thought, then. |
This is in unreleased code so at least for me, this is something I can probably work out alternatives for if this was unintended. There is some concern there may be others relying on the same behaviour though. |
@@ -187,7 +187,10 @@ function mapSelectors( selectors, store, registry ) { | |||
* @return {Object} Actions mapped to the redux store provided. | |||
*/ | |||
function mapActions( actions, store ) { | |||
const createBoundAction = ( action ) => ( ...args ) => store.dispatch( action( ...args ) ); |
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.
For me this was an intended behavior though. It was explicitely meant to address the issue solved by the PR.
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.
For me this was an intended behavior though. It was explicitely meant to address the issue solved by the PR.
What is the intended behavior? I need to check again, but as I understand the bug to be is that nothing will be returned by promise middleware (the first in the chain) in the current master
branch. The change on this line seeks only to preserve that. Otherwise, what is the expected return value when dispatching an action?
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.
I think the expected return value here is a promise that is resolved once all the action flow (controls, sync actions...) is finished.
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.
I'm wondering if we're getting mixed up on the expectations of a dispatch which occurs via the result of the public interface wp.data.dispatch
, and that of the internal store.dispatch
, where the latter does in-fact (and still, after these changes) return a promise.
await store.dispatch( action ); |
I tested again on master
, and neither a synchronous nor control action returns anything through wp.data.dispatch
:
wp.data.dispatch( 'core/editor' ).editPost( { title: 'hello' } );
// undefined
wp.data.dispatch( 'core/editor' ).savePost();
// undefined
However, it was the case that generator actions would return promises as of v5.3.0 .
wp.data.dispatch( 'core/editor' ).editPost( { title: 'hello' } );
// undefined
wp.data.dispatch( 'core/editor' ).savePost();
// Promise {<pending>}
This aligns with @nerrad 's earlier comment. I suspect it changed as a result of #14634.
So, the question(s) then are: Was it intentional to return a Promise
for wp.data.dispatch
and not just the internal store.dispatch
? If so, shall we restore that behavior? And should it return a Promise for the synchronous editPost
as above, or would it be fine enough since it would be normalized to a resolved promise in the context of await or a then
return value (but not directly .then
-able itself without manually normalizing via Promise.resolve
).
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.
It has been beneficial in our ("our" meaning the team I work with implementing the data api, not "our" meaning the GB team) usage that action generators result in a returned promise as there are many use-cases where the result of a save/update could be utilized immediately in further dispatched actions specific to an implementation (as opposed to general via the action). So I'm not opposed to leaving it as. I do think having "regular" actions not returning anything is fine.
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.
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.
wp.data.dispatch( 'somestore').someActionGenerator()
has returned a pending promise for quite a while now. I don't think #14634 introduced it.
I'm suggesting it did the opposite: It removed it.
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.
YIKES! It did! I haven't tested my work against the latest GB for a while. So things are broke :( (for us).
All said and done, this pull request currently behaves identically to what exists today in It seems like there's some open question as to what |
@aduth I'm good with this getting merged in. If I did a pull restoring the response of |
That sounds reasonable, sure. Much of what confused me here is that we were never explicit in what behavior we expect from It's probably more appropriate to share my opinions on a pull request, but I also hope (a) introducing imperative patterns (following a promise resolution vs. subscribing for updates) doesn't contradict existing patterns and (b) we don't expose (resolve to) the actual action object(s), which ought continue to be treated as an implementation detail. Other than that, I don't really have much of an objection to the idea that |
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.
let's get this in 👍
Related: #14634 (comment)
This pull request seeks to resolve an issue with resolver behavior where resolution is marked as finished before the results of a generator control have finished. This is due to the fact that we await the result of
store.dispatch
as if it would return an action, but the order of the middleware chain is such that the promise resolvers cache middleware runs first, and it previously would always returnundefined
(ignoring the fact that the result ofnext
was the promise returned byredux-routine
), causing the resolution to be marked as finished immediately.gutenberg/packages/data/src/namespace-store/index.js
Line 260 in edf6b37
gutenberg/packages/data/src/resolvers-cache-middleware.js
Line 33 in edf6b37
gutenberg/packages/redux-routine/src/runtime.js
Line 48 in edf6b37
Testing instructions:
Verify that unit tests pass:
As I was only able to reproduce in a local working branch, I am not certain steps to verify the behavior in the application. As an alternative, it should be sufficient to verify that other resolved behaviors work as expected (e.g. saving a post).