This question may sound weird, because most of the time popstate is fired synchronously as users press the back button.
However, W3C spec states that a UA (browser) is allowed to queue popstate when traversing history (see item 14), ie. popstate
is fired asynchronously (even though URL has changed at this point).
Browser vendors interpret and implement this spec differently. Mozilla decides Firefox should be able to fire popstate
before load
, and for good reasons, so that slow images will not block popstate
.
Chrome/Safari decides otherwise, and it leads our problem:
When managing history for a web app, it's often desirable to kick off history management as soon as possible, eg. at DOMContentLoaded
instead of load
. But in return, users are not able to back out of any pushState
, because all popstate
are queued until load
.
We are seeking advices for ways to handle such scenario. I e up with a few myself:
load
can fire ASAP.load
is fired.load
instead of DOMContentLoaded
.Are there better solutions?
Update: Things get ugly when there are ajax that fire before load
, if those request result in DOM change, and DOM change happens to have some images, load
is delayed until those images are loaded/timeout, meaning popstate
is queued for even longer.
Update 2: To add a simple demo for it, visit this jsbin page with chrome and see popstate
will be blocked until load
is fired. You can pare result between cached image and uncached image.
This question may sound weird, because most of the time popstate is fired synchronously as users press the back button.
However, W3C spec states that a UA (browser) is allowed to queue popstate when traversing history (see item 14), ie. popstate
is fired asynchronously (even though URL has changed at this point).
Browser vendors interpret and implement this spec differently. Mozilla decides Firefox should be able to fire popstate
before load
, and for good reasons, so that slow images will not block popstate
.
Chrome/Safari decides otherwise, and it leads our problem:
When managing history for a web app, it's often desirable to kick off history management as soon as possible, eg. at DOMContentLoaded
instead of load
. But in return, users are not able to back out of any pushState
, because all popstate
are queued until load
.
We are seeking advices for ways to handle such scenario. I e up with a few myself:
load
can fire ASAP.load
is fired.load
instead of DOMContentLoaded
.Are there better solutions?
Update: Things get ugly when there are ajax that fire before load
, if those request result in DOM change, and DOM change happens to have some images, load
is delayed until those images are loaded/timeout, meaning popstate
is queued for even longer.
Update 2: To add a simple demo for it, visit this jsbin page with chrome and see popstate
will be blocked until load
is fired. You can pare result between cached image and uncached image.
popstate
should always fire immediately. The only case where it does not fire is when you refresh, but in that case you best base yourself on the URI either way (that's the point of a refresh). I must be missing something, but not sure what.
– David Mulder
Commented
Jun 13, 2014 at 17:31
load
has happened... why in the world are you doing that? Only a user should ever change state and the first time the app loads the back button shouldn't have any previous app specific states, so I am thoroughly confused what you're trying to do.
– David Mulder
Commented
Jun 14, 2014 at 12:38
Can you try calling popstate during unload of the previous page. For eg, if you're in page 1 and want to move to page 2, instead of calling pop state during the load/ready of page 2, why don't you call pop state in the unload event of the page 1?
Not sure whether it satisfies your scenario. But I wasn't able to try it in your bin.