Skip to content
This repository has been archived by the owner on Dec 16, 2023. It is now read-only.

Asynchronous pushState is causing some trouble with Backbone routing #781

Closed
bjmiller opened this issue Oct 22, 2014 · 13 comments
Closed

Asynchronous pushState is causing some trouble with Backbone routing #781

bjmiller opened this issue Oct 22, 2014 · 13 comments

Comments

@bjmiller
Copy link

After snooping around the code to find out why things were failing to render in zombie even though they're working just fine in FF/Chrome, I discovered that pushState was made asynchronous.

The routes in an app that I'm working on make the assumption that the URL and history will change immediately when pushState is called, and the code that runs after it in the same turn of the event loop will be able to refer to the current state of those things if necessary.

Can we add a flag to force synchronous state changes to history? It looks like this is where my problems may have started: 038b3c6

I'm not sure if there's an easy way to change or rewrite my application code so that this isn't a problem.

@assaf
Copy link
Owner

assaf commented Oct 22, 2014

Can you add a test case?

@bjmiller
Copy link
Author

I've added a PR with the failing tests that you requested. Please let me know if you have any questions, or if I can be of further assistance.

@assaf
Copy link
Owner

assaf commented Oct 23, 2014

Fixed in 2.1.1

@assaf assaf closed this as completed Oct 23, 2014
@bjmiller
Copy link
Author

Thank you for the help and quick response! This is very helpful, in that I can work around my current problem to at least get my test green.

I'm almost to where my original test is passing, but not quite. Unfortunately, Backbone's internal history object (which ultimately uses the window's history and location objects) is suffering from a similar problem, such that Backbone's history.getFragment() method isn't returning an updated url from the location object, even though the actual url is now reporting correctly. I think the culprit may be here: https://github.com/assaf/zombie/blob/master/src/zombie/history.coffee#L324, as these methods are also waiting for the next turn of the event loop.

If you need another test case for this, please let me know. This one might be a little bit more complicated, and I may not be able to get to it until the week after next sometime.

@assaf
Copy link
Owner

assaf commented Oct 24, 2014

If you change the document location, that change doesn't happen immediately. If you change anything else in the history, that change can happen immediately. So that requires some other change to get working, and of course test to cover the difference scenarios.

@yanovich
Copy link
Contributor

We test an angular.js app using zombie and hit angular/angular.js#3915 (comment) 10 $digest() iterations reached using $locationWatch

It seems FF/Chrome update document location synchronously and angular.js relies on sync updating.

If you change the document location, that change doesn't happen immediately. If you change anything else in the history, that change can happen immediately.

@assaf, could you elaborate a bit on where this spec comes from.

@assaf
Copy link
Owner

assaf commented Nov 13, 2014

Try it in a browser. The browser doesn't navigate to a new URL until after your script finishes, and document.location doesn't change until after it navigates to a new URL.

What you're talking about is the document fragment identifier that changes the current scroll position within the document and the history object, but doesn't navigate the browser to a new location.

@yanovich
Copy link
Contributor

@assaf. Great job. We are late with our pull request.

@bjmiller
Copy link
Author

Sorry I'm so late commenting on this. The behavior as described isn't entirely correct.

When you type a new URL into the location bar of Chrome/FF, the location object updates after the page loads. But, when you use pushState, it updates immediately. The fact that it doesn't work that way in Zombie is what's gumming up both Backbone and the Angular ui-router.

Can we make that change? I can submit failing test cases for this, if you'd like.

@yanovich
Copy link
Contributor

@bjmiller, Everything looks nice in the respect in v.2.2.1. It's worth to update zombie package.

@bjmiller
Copy link
Author

It seems that for my case, Backbone.history.getFragment() is still not returning the correct value in my test when using 2.2.1. So, it's still a problem for me.

@assaf
Copy link
Owner

assaf commented Nov 21, 2014

You'll have to narrow it down further and submit a test case. I'm not going to dig into the internals of Backbone/Angular since I use neither.

@bjmiller
Copy link
Author

After some digging, I've discovered something even weirder. Backbone creates a reference to the location and history objects like this:

this.location = window.location;

But, immediately after that, I try inserting a console.log to see what's going on...

console.log( this.location === window.location ); // => false ... WTF?

I've managed to work around my problem locally, since window.location behaves properly now, even if Backbone.history.location won't in Zombie's context. But, there is something fishy about all this, and I'll try investigating further if I have the time.

Thanks for being patient.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants