angular: Signals don't trigger change detection using native async/await (ES2017+)

Which @angular/* package(s) are the source of the bug?

Don’t known / other

Is this a regression?

No

Description

See the stackblitz for replication.

When using ES2017+, the native async/await version, setting a signal after an await statement does not cause change detection to run. I assume that the component is marked for check, but nothing triggers a change detection cycle.

However, using the async pipe and observables in the same scenario does cause change detection to run. In fact, if you look at the stackblitz, change detection runs properly and the expected behaviour occurs just by creating a new component property using toObservable of the signal, without even using it in the template or anywhere else.

Setting the target to ES2015 also causes the expected behaviour to occur. As does using .then instead of async/await, and as does setting the signal inside of a zone.run callback.

I understand the older open issues that zone.js cannot patch the native async/await. However, signals are described to be able to trigger change detection without the need for zone.

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/stackblitz-starters-vetml3?file=src%2Fmain.ts

Please provide the exception or error you saw

Did not see change detection run.

Please provide the environment you discovered this bug in (run ng version)

{
  "name": "stackblitz-starters-vetml3",
  "version": "0.0.0",
  "private": true,
  "dependencies": {
    "rxjs": "7.8.1",
    "tslib": "2.6.2",
    "zone.js": "0.14.2",
    "@angular/core": "17.0.2",
    "@angular/forms": "17.0.2",
    "@types/jasmine": "4.3.6",
    "@angular/common": "17.0.2",
    "@angular/router": "17.0.2",
    "@angular/compiler": "17.0.2",
    "@angular/animations": "17.0.2",
    "@angular/platform-browser": "17.0.2"
  },
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.4",
    "@angular/cli": "~11.0.4",
    "@angular/compiler-cli": "~11.0.4",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2"
  }
}

Anything else?

Related: https://github.com/angular/angular/issues/31730

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Comments: 17 (9 by maintainers)

Commits related to this issue

Most upvoted comments

My comments are in a world with native async/await. I suspect the differences may occur if, for some reason, async/await is being downleveled to use generators and the Promise constructor, as then zone.js would have been able to monkey-patch that Promise constructor.

This is sort of expected, although unfortunate.

Native async/await is not visible to zone.js, so any activity in those async stack frames does not automatically trigger change detection (signals, at least today, only manage reactive dependencies, they do not initiate change detection scheduling).

Since there isn’t any other activity going on the page, change detection is just never scheduled again.