Skip to content
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

Merged
merged 11 commits into from Aug 25, 2017

Conversation

dreamofabear
Copy link

@dreamofabear dreamofabear commented Apr 10, 2017

Fixes #10914.

  • Add a {?Promise} return type to action handlers.
  • If an action handler returns a Promise, subsequent actions triggered by the same event will wait for the Promise to resolve before invocation.
  • Only allow a single AMP.setState per action "chain" to sidestep performance constraint issue (for now).

Related: #8648 (comment).

@dreamofabear dreamofabear changed the title amp-bind: Actions after setState will wait for its completion [WIP] Actions after AMP.setState will wait for its completion Apr 12, 2017
@edhollinghurst
Copy link
Contributor

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

@dreamofabear
Copy link
Author

@edhollinghurst Would you mind describing your use case? This PR was exploratory in nature.

@edhollinghurst
Copy link
Contributor

@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)

@dreamofabear
Copy link
Author

@edhollinghurst Thanks. Does using amp-state with a [src] binding not fit your use case (the second suggestion on the same comment)?

@edhollinghurst
Copy link
Contributor

@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.

@dreamofabear dreamofabear mentioned this pull request Aug 15, 2017
@dreamofabear dreamofabear changed the title [WIP] Actions after AMP.setState will wait for its completion [Experimental] Actions after AMP.setState will wait for its completion Aug 15, 2017
@dreamofabear dreamofabear changed the title [Experimental] Actions after AMP.setState will wait for its completion [Experimental] Actions after AMP.setState will wait for its completion Aug 15, 2017
@dreamofabear dreamofabear force-pushed the bind-ecommerce-xhr branch 2 times, most recently from fe275f1 to c419788 Compare August 15, 2017 23:09
@dreamofabear dreamofabear changed the title [Experimental] Actions after AMP.setState will wait for its completion Support action chaining (for multiple actions in a single event) Aug 17, 2017
@dreamofabear
Copy link
Author

/to @alanorozco /cc @dvoytenko

@dreamofabear
Copy link
Author

@alanorozco Friendly ping.


// Wait for the previous action, if applicable.
currentPromise = (currentPromise)
? currentPromise.then(() => invoke())
Copy link
Contributor

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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// Wait for the previous action, if applicable.
currentPromise = (currentPromise)
? currentPromise.then(() => invoke())
: invoke();
Copy link
Contributor

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?

Copy link
Author

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.

Copy link
Contributor

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.

Copy link
Author

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.

// Only allow one AMP.setState action per event.
const actionInfos =
/** @type {!Array} */ (dev().assert(opt_actionInfos));
const firstSetState = findIndex(actionInfos, actionInfo => {
Copy link
Contributor

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

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -392,7 +392,7 @@ export class ActionService {

// Wait for the previous action, if applicable.
currentPromise = (currentPromise)
? currentPromise.then(() => invoke())
? currentPromise.then(invoke())
Copy link
Contributor

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. 😛

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. 😄

// Wait for the previous action, if applicable.
currentPromise = (currentPromise)
? currentPromise.then(() => invoke())
: invoke();
Copy link
Contributor

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.

@cvializ
Copy link
Contributor

cvializ commented Aug 24, 2017

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.

@dreamofabear
Copy link
Author

@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.

@dreamofabear
Copy link
Author

@jridgewell Any other comments?

@dreamofabear dreamofabear merged commit 4788fd9 into ampproject:master Aug 25, 2017
@dreamofabear dreamofabear deleted the bind-ecommerce-xhr branch August 25, 2017 17:58
@edhollinghurst
Copy link
Contributor

Thanks for this @choumx !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

amp-bind ordering
6 participants