HTML5 History API: JSON displayed when going “back

2019-02-08 17:37发布

问题:

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?

回答1:

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.



回答2:

There is a cache option for $.ajax:

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

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



回答3:

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