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
Support action chaining (for multiple actions in a single event) #8678
Support action chaining (for multiple actions in a single event) #8678
Conversation
setState
will wait for its completionAMP.setState
will wait for its completion
I have a vested interest in getting this in for a project I'm working on. Is there anything I can do to help? @bjalford FYI |
@edhollinghurst Would you mind describing your use case? This PR was exploratory in nature. |
@choumx Yes I'm just to use amp-bind to set the field values on a hidden form before triggering it to submit. Basically the first scenario that you describe here: #8648 (comment) |
@edhollinghurst Thanks. Does using |
@choumx Thanks. I'm not sure it will work for my use case though as I'm looking to POST to the backend. I've created an example here: https://www.edhollinghurst.com/amp-bind-voting/amp-bind-voting.html For this example I've not actually set up a backend for the form to post to but hopefully you get the idea of what I'm trying to achieve. |
AMP.setState
will wait for its completionAMP.setState
will wait for its completion
74c146c
to
74ceb53
Compare
AMP.setState
will wait for its completionfe275f1
to
c419788
Compare
/to @alanorozco /cc @dvoytenko |
@alanorozco Friendly ping. |
src/service/action-impl.js
Outdated
|
||
// Wait for the previous action, if applicable. | ||
currentPromise = (currentPromise) | ||
? currentPromise.then(() => invoke()) |
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.
Nit: no need for a second closure 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.
Done.
src/service/action-impl.js
Outdated
// Wait for the previous action, if applicable. | ||
currentPromise = (currentPromise) | ||
? currentPromise.then(() => invoke()) | ||
: invoke(); |
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 might return null, right?
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.
Yes. All actions up to the first one that returns a Promise will execute synchronously.
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.
What I mean is that the first promise might actually be null
, and doing null.then
is an error.
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.
If invoke()
returns null, then during the next iteration it'll fall into the "else" branch of the ternary again, no? Note that currentPromise
is initialized to null
.
src/service/standard-actions-impl.js
Outdated
// Only allow one AMP.setState action per event. | ||
const actionInfos = | ||
/** @type {!Array} */ (dev().assert(opt_actionInfos)); | ||
const firstSetState = findIndex(actionInfos, actionInfo => { |
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.
Nit: use a for loop and limit to opt_actionIndex
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.
Done.
src/service/action-impl.js
Outdated
@@ -392,7 +392,7 @@ export class ActionService { | |||
|
|||
// Wait for the previous action, if applicable. | |||
currentPromise = (currentPromise) | |||
? currentPromise.then(() => invoke()) | |||
? currentPromise.then(invoke()) |
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.
Not quite. You want to pass the invoke function, not call 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.
Oops. 😄
src/service/action-impl.js
Outdated
// Wait for the previous action, if applicable. | ||
currentPromise = (currentPromise) | ||
? currentPromise.then(() => invoke()) | ||
: invoke(); |
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.
What I mean is that the first promise might actually be null
, and doing null.then
is an error.
Do you have an example of the syntax for chaining actions? Looking at the source it's not obvious what it might look like in the markup. |
@cvializ There's no new syntax, just a behavior change. For example: <!-- #form1 will wait for AMP.setState to complete before invoking `submit`. -->
<button on="tap:AMP.setState({x: 123}), form1.submit"> The link on OP has more usage context. |
b430566
to
9a7bead
Compare
9a7bead
to
8f518ac
Compare
@jridgewell Any other comments? |
Thanks for this @choumx ! |
Fixes #10914.
{?Promise}
return type to action handlers.AMP.setState
per action "chain" to sidestep performance constraint issue (for now).Related: #8648 (comment).