-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Fix infinite digest loop triggered by changing $location.path() #3951
Conversation
Thanks for the PR!
If you need to make changes to your pull request, you can update the commit with Thanks again for your help! |
Just signed CLA. |
On Android 2.2 and 2.3, infinite digest loops are occasionally triggered by changing $location.path() The problem is caused by a faulty assumption in $browser.onUrlChange(). The assumption is that the hashchange event will only fire as a result of non-Angular actions, e.g. a human editing the browser's url. Unfortunately in Android 2.2 and 2.3, this occasionally fires when browser.url() changes the url. The knock-on effect is a race condition between $location's two monitoring loops: one watches for manual browser url changes using $browser.onUrlChange and updates $location's inner data, while the other ($locationWatch) watches for changes in $location.absUrl() and synchs them to $browser. They end up reversing each other's changes in a vicious cycle until Angular cuts them off.
Had the same problem on Kindle Fire on Android 2.3. This solve it. 👍 |
Fixed on Nexus One 2.3.6 😂 |
Strangely it works well on 2.3, but I still have routing problem on android 4.0.4, no idea why yet. |
@bcharp : Does it appear to be the same problem? My fix works only with Android versions that don't properly support the history API, namely version < 4. For it to take effect on everything, and it should not do any harm, add the ignoreHashChange = true/false around lines 157-162:
Does that fix it? |
Thanks a lot, works fine for me! |
This is a refactor of the proposed solution, which guards against changing the url() from inside the location watcher.
@xrg I see that you increased the scope of the fix. I thought of doing this, but didn't because:
|
Indeed, I have written "1" because I was trying to eliminate the possibility of url change in a wider sense. Turned out that it was not the real problem, at the end of the day. About "2", it is a subjective fix, since (as you say) the browser will have even bigger trouble than a stale flag. But still, cleaning the stale flag wouldn't do any harm, would it? The exception would propagate anyway. |
I agree that your expanded fix is fine -- it works and does not cause any problems. I think our opinions differ on what is considered optimal for a fast-moving framework such as Angular, and that's OK. |
Agreed. Let's move on to the rest of unresolved bugs! |
Many thanks, also works for me! |
Is this problem solved with 1.2.1 ? |
Why has this not been merged yet? |
@peey It's bitrotten, there are no tests, and our CI is not running on any mobile devices currently anyways (although hopefully this will change soon) |
02dc2aa
to
fd2d6c0
Compare
cad9560
to
f294244
Compare
e8dc429
to
e83fab9
Compare
4dd5a20
to
998c61c
Compare
So this was not complete (missing tests) for a while and got bit-rotten over 6 months ago so I don't think we can consider landing this one. @isabo there were recently tons of fixes about #-handling and infinite loops in master so please try the latest version to see if it fixes problems for you. If not please open a new issue with a reproduce scenario (or even better - a pull request with tests!). Thnx! |
Web apps that use the $route module will typically not work on Android 2.x without this fix.
On Android 2.x, using
$location.path()
to change the url occasionally triggers an infinite digest iterations exception for no good reason.The problem is caused by a faulty assumption in
$browser.onUrlChange()
. The assumption is that thehashchange
event will fire only as a result of non-Angular actions, e.g. a human editing the browser's url. Unfortunately in Android 2.2 and 2.3, this event occasionally fires when Angular's own$browser.url()
changes the url.The knock-on effect is a race condition between $location's two monitoring loops:
$browser.onUrlChange()
to get notified about non-Angular url changes and synchs$location
's inner data.$locationWatch()
, watches for changes in$location.absUrl()
and synchs them to$browser
.They end up reversing each other's changes in a vicious cycle until Angular cuts them off. Meanwhile the browser gets stuck and goes nowhere.
Closes #3814