ccrisan ccrisan - 1 month ago 8
Javascript Question

history.back() doesn't work with HTML5 history API as expected in Chrome

The

history.back()
function is supposed to take me back one step in the history created using HTML5 history API. The following code works as expected in Firefox but does not in Chrome:

<html>
<script type="text/javascript">
history.replaceState({path: '/home'}, '', '?page=home');
history.pushState({path: '/second'}, '', '?page=second');
console.log(history.state.path); // says "/second"
history.back();
console.log(history.state.path); // says "/second" but should say "/home"
</script>
</html>


In Chrome, it prints
/second
both times, whereas after going back it should print
/home
. Am I missing something?

Answer

In Chrome, history.back / history.forward / history.go are not synchronized with history.state. I encountered this issue a while back while working on PDF.js, and reported it at Chromium's issue tracker: https://crbug.com/510026. Nothing has come out of it though.

A work-around is to use the popstate event to detect when the navigation finishes:

history.replaceState({path: '/home'}, '', '?page=home');
history.pushState({path: '/second'}, '', '?page=second');
console.log(history.state.path); // says "/second"

addEventListener('popstate', function(event) {
  console.log(history.state.path); // says "/home"
  // You can also use console.log(event.state);
}, {once: true});
history.back(); // Will asynchronously change history.state

Note: addEventListener with the once parameter is only supported as of Chrome 55 - before that you have to call removeEventListener in the listener if you want a listener to run once, like this:

addEventListener('popstate', function listener(event) {
  removeEventListener('popstate', listener);
  console.log(history.state.path); // says "/home"
  // You can also use console.log(event.state);
});