angular: UpgradeModule: Exception in $digest breaks change propagation

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

When $rootScope.$digest throws an exception ($digest already in progress), change propagation stops working for downgraded components.

That is because the exception breaks the subscription on onMicrotaskEmpty here:

https://github.com/angular/angular/blob/master/packages/upgrade/src/static/upgrade_module.ts#L244

setTimeout(() => {
  const $rootScope = $injector.get('$rootScope');
  const subscription = this.ngZone.onMicrotaskEmpty.subscribe(() => $rootScope.$digest());
  $rootScope.$on('$destroy', () => { subscription.unsubscribe(); });
}, 0);

Expected behavior

UpgradeModule should be more fault tolerant (try-catch?) or Use a different pattern. (Check if digest already running?)

Minimal reproduction of the problem with instructions

I get this “$digest already in progress” almost every time I open an angularjs material dialog or a sidenav.

What is the motivation / use case for changing the behavior?

Environment


Angular version: 6.0.X


Browser:
- [x] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 1
  • Comments: 29 (16 by maintainers)

Commits related to this issue

Most upvoted comments

@MikeMatusz, I don’t think it matters. Why do you want to always run $digest() from inside the Angular zone? This also doesn’t sound related to this issue.

In any case, if anyone is looking for a (quick and dirty) work around for this issue, you could monkeypatch $rootScope.$digest() to not run if a $digest()/$apply() is already in progress. E.g.:

angular.
  module('myApp').
  decorator('$rootScope', $delegate => {
    const originalDigest = $delegate.$digest;
    $delegate.$digest = () => {
      if (!$delegate.$$phase) {
        originalDigest.call($delegate);
      }
    };
    return $delegate;
  });

Sounds good I’ll try to get a PR ready tomorrow!

Sorry I haven’t gotten to this yet! Hope to do it soon

Here it is:

https://ngupgradestatic-playground-26mk87.stackblitz.io/

Counter stops refreshing after button is clicked.

It is somehow related to __Zone_disable_requestAnimationFrame = true; (but this really speeds up my hybrid app.)

Do I need to open another issue?