-
Notifications
You must be signed in to change notification settings - Fork 26
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
Allow multiple event handlers to call respondWith()
#94
Comments
Regarding this comment, one interesting piece of feedback from #66 is that both Vue and Angular navigations are async (all Vue navigations, and Angular navigations by default). Does that feedback affect this decision? |
Not really, since they are frameworks that handle all navigations, and so they can synchronously decide to always call |
This ensures that if multiple event handlers are in place, appHistory.current and location.href only update after they all have finished. Part of #94.
This ensures that if multiple event handlers are in place, appHistory.current and location.href only update after they all have finished. Part of #94.
Quoting #89 (comment):
The last of these is done. I'm interested in feedback on which, if any, of the first three of these we should do. |
Discussing this a bit offline with @tbondwilkinson, we're thinking that allowing multiple calls to During that discussion, we thought there were two alternatives: I'm going to draft a |
Hmm, if we do this, we may want to rename I guess |
Part of #94. As discussed there, this uses Promise.all()-like semantics, so that the navigatesuccess/navigateerror event and navigate() promise resolution are delayed on the aggregate of all promises passed to respondWith(). This does mean that navigate() no longer fulfills with the same value as the promise passed to respondWith() fulfills with, since we allow multiple such promises and it's not clear which value to choose now. But that was always a bit of a strange way of smuggling information around. This also slightly changes the interaction with event cancelation (i.e., preventDefault()). Previously, calling respondWith() would cancel the event (observable using, e.g., defaultPrevented). Thus, canceling the event after calling respondWith() was a no-op. Now, they are independent operations: calling respondWith() does not cancel the event, and if you cancel the event after calling respondWith(), this will immediately cancel the navigation. This also contains a bugfix where previously calling appHistory.navigate(url, { state: newState }) and then removing the relevant iframe from the DOM during a navigate event handler would still attempt to set the new state, even though doing so canceled the navigation. Now all paths to "synchronously finalize with an aborted navigation error" (formerly "signal an aborted navigation") clear the pending app history state change.
Part of #94. As discussed there, this uses Promise.all()-like semantics, so that the navigatesuccess/navigateerror event and navigate() promise resolution are delayed on the aggregate of all promises passed to respondWith(). This does mean that navigate() no longer fulfills with the same value as the promise passed to respondWith() fulfills with, since we allow multiple such promises and it's not clear which value to choose now. But that was always a bit of a strange way of smuggling information around. This also slightly changes the interaction with event cancelation (i.e., preventDefault()). Previously, calling respondWith() would cancel the event (observable using, e.g., defaultPrevented). Thus, canceling the event after calling respondWith() was a no-op. Now, they are independent operations: calling respondWith() does not cancel the event, and if you cancel the event after calling respondWith(), this will immediately cancel the navigation. This also contains a bugfix where previously calling appHistory.navigate(url, { state: newState }) and then removing the relevant iframe from the DOM during a navigate event handler would still attempt to set the new state, even though doing so canceled the navigation. Now all paths to "synchronously finalize with an aborted navigation error" (formerly "signal an aborted navigation") clear the pending app history state change. As discussed in #94, this makes the name respondWith() less appropriate, since the service worker respondWith() method we were drawing an analogy with prohibits such multiple calls (by performing the equivalent of stopImmediatePropagation()). We will likely rename respondWith() in a followup.
I'm no longer convinced. Although after #126 In particular, So, probably we should come up with a totally new name, not related to the events seen in service workers. Maybe... |
Naming things is hard!
Yeah I don't know, I'm bad at this game. 🙂 |
Part of #94. As discussed there, this uses Promise.all()-like semantics, so that the navigatesuccess/navigateerror event and navigate() promise resolution are delayed on the aggregate of all promises passed to respondWith(). This does mean that navigate() no longer fulfills with the same value as the promise passed to respondWith() fulfills with, since we allow multiple such promises and it's not clear which value to choose now. But that was always a bit of a strange way of smuggling information around. This also slightly changes the interaction with event cancelation (i.e., preventDefault()). Previously, calling respondWith() would cancel the event (observable using, e.g., defaultPrevented). Thus, canceling the event after calling respondWith() was a no-op. Now, they are independent operations: calling respondWith() does not cancel the event, and if you cancel the event after calling respondWith(), this will immediately cancel the navigation. This also contains a bugfix where previously calling appHistory.navigate(url, { state: newState }) and then removing the relevant iframe from the DOM during a navigate event handler would still attempt to set the new state, even though doing so canceled the navigation. Now all paths to "synchronously finalize with an aborted navigation error" (formerly "signal an aborted navigation") clear the pending app history state change. As discussed in #94, this makes the name respondWith() less appropriate, since the service worker respondWith() method we were drawing an analogy with prohibits such multiple calls (by performing the equivalent of stopImmediatePropagation()). We will likely rename respondWith() in a followup.
Suggestion:
Aside:
This blew my mind a bit to learn just now. I never realized the |
The only potential problem with So in my mind it's between
|
I'm not completely sold on these names. My problem with "convert" is that it doesn't convert in all cases - sometimes the navigation is already a same-document navigation, like if it's a traversal or if it's history.pushState. My proposal is transitionUntil() or like deferTransition() or extendTransition() |
What did you think of @bathos's arguments for why |
I should qualify re: verbWhile / verbUntil that I realize it’s a pretty subtle distinction being made and neither word achieves instantaneous “I definitely know how THIS will behave!” nirvana. If folks think the existing usage of |
I found the multiple promises point pretty compelling. |
Fair enough, I'm fine with While |
It doesn't. |
@jakearchibald thanks for the info — that’s exactly what my understanding had been prior to reading that and I was very surprised to learn otherwise (or think I was learning otherwise, rather). Do you know what the quoted statement (“fetchEvent.waitUntil() buffers other fetch events until the current one completes”) was referring to? (i.e. was that itself incorrect or did i just misunderstand what it was saying?) |
The only time waitUntil delays fetch events is when it's called on the activate event. This is because activate is the time the old service worker is gone - it's when you can perform migrations etc that couldn't be run while the old service worker was controlling pages, but that are needed before the new service worker fully takes over. |
Thanks, that makes perfect sense. (Though I still never totally trust my mental model of the lifecycle without verifying stuff against the spec, it’s probably gotten pretty solid at this point. However I doubt I’d have learned any of it in the first place if not for what was and probably still is the greatest dev intro ever written for a new platform API & its capabilities :) |
Ohh wow thanks! There's also https://web.dev/service-worker-lifecycle/ which covers some of the lifecycle stuff. |
Forked from the discussion here: #89
Some key comments from @domenic :
#89 (comment)
#89 (comment)
And highlights below as well
Currently only one handler can call
respondWith()
:Some additional thoughts from @tbondwilkinson
The text was updated successfully, but these errors were encountered: