12

I have a page where there are several search / filter button which, when clicked, refresh the contents of a list below through AJAX.

In the process, I'm modifying history (through pushstate) so that the new filtered page is bookmarkable, and so the back button works. I'm also listening for the popstate event, to react to Back.

My code looks more or less like this:

window.addEventListener("popstate", function(ev) {
  if (!window.history_ready) { return; } // Avoid the one time it runs on load 
  refreshFilter(window.location.href, true);
});

refreshFilter: function(newURL, backButtonPressed){
  $.ajax({ url: newURL}).done( blah );

  if (!backButtonPressed) {
    window.history_ready = true;
    history.pushState(null, null, newURL);
  }
}

This works wonderfully, except for one weird case...

  • User is in page "A"
  • They click a link to go to this page that plays with history (let's call it "B")
  • They run a couple of filters, then press Back a few times, so they're back at the initial state of "B"
  • They click Back once again, which sends them back to "A"
  • At this time, if they press Forward, instead of making a request to the server again for Page "B", the browser simply displays a bunch of JSON code as the page contents (this JSOn is the response of one of my AJAX requests to filter stuff)

At least in latest Chrome

Why is this happening and how can I avoid it?

Jack P.
  • 11,287
  • 1
  • 26
  • 33
Daniel Magliola
  • 27,613
  • 56
  • 154
  • 235

3 Answers3

14

Chrome caches the pages you visit and when you go back or forward it uses the cache to display the page quickly. If the URLs you are using to retrieve JSON from the server by AJAX is the same one Chrome would hit, then it's possible Chrome is picking that page from the cache, which instead of being the nice HTML it's just a JSON dump.

pupeno
  • 256,034
  • 114
  • 324
  • 541
  • 7
    I tried the implied solution — changed the URLs fetched by AJAX slightly (by adding a completely ignored `&ajax=1` to the query string) — and it worked! :) – Asherah Jan 27 '14 at 12:43
  • 1
    Notably, you may want to clear your Chrome cache when trying this solution. It might seem like Chrome still isn't working after trying this because it has cached an old result. – jonnybot Dec 01 '15 at 16:59
  • @jonnybot Thanks, I thought the fix was working for everybody else but for me, but after clearing the cache it started working and the bug is gone. – sandre89 Nov 05 '17 at 20:54
5

There is a cache option for $.ajax:

$.ajax({ cache: false, url: newURL})

See http://api.jquery.com/jquery.ajax/

Oldskool
  • 32,791
  • 7
  • 50
  • 64
v0id
  • 73
  • 1
  • 4
0

@pupeno is right, but to give a more solution oriented answer, you need to differentiate the JSON from HTML in the routes your server has.

I know two ways of doing this:
1) If you call /users you get HTML, if you call /users.json you get JSON.
2) If you call /users you get HTML, if you call /api/users you get JSON.

I like 1 a lot better, but it depends on the web framework if whichever is used by default or wether you configure that yourself.
1 is used in Ruby on Rails, 2 is used in other frameworks too.

erandros
  • 1,645
  • 3
  • 17
  • 42