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

Turbo does not cancel pending requests that were prefetched on consecutive link clicks #1244

Open
ilyadh opened this issue Apr 14, 2024 · 0 comments

Comments

@ilyadh
Copy link

ilyadh commented Apr 14, 2024

In a situation when page loads or internet connection are slow, clicking multiple links within a short period of time should only load the last link clicked.
When prefetch is disabled, Turbo works correctly by canceling pending requests issued by previous clicks.

When prefetch is enabled however, all requests issued by clicks will run to completion. The page will re-render on each completed request resulting in flickering. And the last link clicked is not guaranteed to be the one visible when all requests complete.

In the following example, there are 3 links that take 2s,6s, and 4s to load. Clicking them consecutively in that order will result in the slowest page being opened last, even though it was a second click, not the last one.

Screen recording of example
turbo-screen-recording-optimized.mov
Example with Rails
require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  gem "rails"
  gem "puma"
  gem "propshaft"
  gem "turbo-rails"
end

require "action_controller/railtie"

class App < Rails::Application
  config.load_defaults "7.1"
  
  config.consider_all_requests_local = true
  config.turbo.draw_routes = false
  
  routes.append do
    root to: "application#index"
  end
end

$template = DATA.read

class ApplicationController < ActionController::Base
  include Rails.application.routes.url_helpers

  def index
    sleep(params[:sleep].to_i) if params[:sleep].present?
    render inline: $template, formats: :html
  end
end

App.initialize!

Rack::Server.new(app: App, Port: 3000).start

__END__
<html>
  <head>
    <script type="importmap">
      {
        "imports": {
          "@hotwired/turbo-rails": "<%= asset_path("turbo.js") %>"
        }
      }
    </script>

    <script type="module">
      import "@hotwired/turbo-rails"
    </script>

  </head>

  <body>
    <h1>page <%= (params[:page].present? ? params[:page] : 'root').upcase %></h1>

    <%= link_to "root", root_path %>
    
    <div data-turbo-prefetch="false">
      <h2>without prefetch</h2>

      <ol>
        <li><%= link_to "slow", root_path(page: 'slow', sleep: 2) %></li>
        <li><%= link_to "slowest", root_path(page: 'slowest', sleep: 6) %></li>
        <li><%= link_to "slower", root_path(page: 'slower', sleep: 4) %></li>
      </ol>
    </div>

    <div>
      <h2>with prefetch</h2>

      <ol>
        <li><%= link_to "slow", root_path(page: 'slow', sleep: 2) %></li>
        <li><%= link_to "slowest", root_path(page: 'slowest', sleep: 6) %></li>
        <li><%= link_to "slower", root_path(page: 'slower', sleep: 4) %></li>
      </ol>
    </div>
  </body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant