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

Ensure response content is loaded before requestFinish is called. #1377

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

armstrjare
Copy link

@armstrjare armstrjare commented Mar 5, 2025

Previously the response content was loaded asynchronously within the FetchRequest delegate. Consequently, the requestFinished callback was called prior this finishing. The requestFinished callback triggers the toggling of the busy attribute on <html>/<turbo-frame>/<form>, the triggering of the afterSubmit callback which toggles the disabled state of form submitters, and the the turbo:submit-end event.

For clients with high latency, this could result in janky behaviour when the busy/disabled state is removed a noticeable time before the response is loaded and rendered.

This change removes this delay by ensuring the response is loaded and available prior to notifying the delegate and continuing execution of the Turbo behaviour.

Resolves #766 #884 #1202
Replaces #1039

Note that I explored other solutions, such as having the FetchRequest await the success handlers, etc. on the delegate. Unfortunately, because of the behaviours tied to the requestFinished callback, this needs to be executed before the response is rendered by the other delegate callbacks, so that the various attribute updates on elements are processed before the PageSnapshot is taken for the cache, and before the existing DOM content is replaced as to not affect user callbacks.

Ultimately, this solution practically resolves the issues, without impacting any other Turbo timings or behaviour.

Previously the response content was loaded asynchronously within the
FetchRequest delegate. Consequently, the requestFinished callback was
called prior this finishing. The requestFinished callback triggers the
toggling of the busy attribute on <html>/<turbo-frame>/<form>, the
triggering of the afterSubmit callback which toggles the disabled state
of form submitters, and the the turbo:submit-end event.

For clients with high latency, this could result in janky behaviour
when the busy/disabled state is removed a noticeable time before the
response is loaded and rendered.

This change removes this delay by ensuring the response is loaded and
available prior to notifying the delegate and continuing execution of
the Turbo behaviour.
@armstrjare
Copy link
Author

Fixed the eslint failure – added teardown to eslint globals

@armstrjare
Copy link
Author

For anyone that wants this fixed for their app before this gets merged, here is a monkey-patch that gives effectively the same outcome:

// Ensure that the responseHTML is loaded before the fetchRequest is declared finished
const originalReceive = Turbo.FetchRequest.prototype.receive
Turbo.FetchRequest.prototype.receive = async function(response) {
  let fetchResponse = await originalReceive.call(this, response)
  await fetchResponse.responseHTML
  return fetchResponse
}

@armstrjare
Copy link
Author

@jorgemanrubia is this something you guys would consider merging? let me know if there is any feedback on this

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

Successfully merging this pull request may close these issues.

Submit button re-enabled after form submit before redirecting user to another page
1 participant