javascript - How to handle back button when browser is not firing popstate event immediately - Stack Overflow

This question may sound weird, because most of the time popstate is fired synchronously as users press

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:

  • Lazyload images, so load can fire ASAP.
  • Block UI until load is fired.
  • Init framework on 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:

  • Lazyload images, so load can fire ASAP.
  • Block UI until load is fired.
  • Init framework on 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.

Share Improve this question edited Jun 14, 2014 at 16:41 bitinn asked Jun 7, 2014 at 11:34 bitinnbitinn 9,35811 gold badges42 silver badges67 bronze badges 8
  • When using the back button 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
  • @DavidMulder I have added a jsbin page to demonstrate the problem. – bitinn Commented Jun 14, 2014 at 12:31
  • Ah, at least I get now that you're firing a history state change before the 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
  • @DavidMulder We try very hard not to. But because 3G network is unstable, we see a lot of users got into issue where images are still loading (thus onload hasn't fired), but js framework has kicked in (as dom is ready). Because we handle history with js, when user cliked a link, pushstate is fired, but onload hasn't fired at this point, so when user click back button, we can't hanle it by listening to popstate. – bitinn Commented Jun 14, 2014 at 12:44
  • 1 Are you building a single state application? If so I think its reasonable to block UI once while initialising. Each page sends a setup script, which initialises then resolves the original url request. People experience a slightly longer load time while your app inits, but should be speed up for future requests. – Lex Commented Jun 15, 2014 at 0:21
 |  Show 3 more ments

1 Answer 1

Reset to default 2 +25

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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745606181a4635685.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信