angular: bug(upgrade): infinite digests with setTimeout (repro inside)

angular2/upgrade has a bug that occurs when an angular1 watcher calls setTimeout, as is the case with many angular1 components.

Repro: http://plnkr.co/edit/5iCEQOSOer5c630FStXv?p=preview

This results in infinite angular1 digests because of this line:

https://github.com/angular/angular/blob/master/modules/angular2/src/upgrade/upgrade_adapter.ts#L341

Changing ngZone.run to ngZone.runOutsideAngular there seems to fix it or make it more manageable.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15 (7 by maintainers)

Commits related to this issue

Most upvoted comments

@petebacondarwin any update? Will this be fixed in the near future?

+1 Any update on this please?

We have some ideas that might help but key people are unavailable this week and next. I’ll update in a couple of weeks

We are generally not keen on changing $digest to $evalAsync for the digest that is run when the microtask queue is empty, because this tends to hide programming errors (which often have hard-to-track-down performance implications).

This unfortunately means that running setTimeout in a watcher will lead to infinite digest errors, unless you change it to run outside of the Angular zone. To be clear, you can still use setTimeout in the watch listener function:

scope.$watch(
  () => {
    // Watch function.
    // Do NOT use `setTimeout()` here (unless you explicitly run it outside the Angular zone).
  },
  () => {
    // Watch listener function.
    // You can use `setTimeout()` here.
  }
)

The new downgradeModule(), which decouples the change detections of the two frameworks, could possibly help in such situations. (Docs will be added with #18487.)