24

After upgrading from Angular 9 to 10 I get these warnings when I run ng serve:

WARNING: Zone.js does not support native async/await in ES2017.
These blocks are not intercepted by zone.js and will not triggering change detection.
See: https://github.com/angular/zone.js/pull/1140 for more information.

(node:56581) ExperimentalWarning: The fs.promises API is experimental

Anybody know what this means and if it is something I should care about?

Liam
  • 27,717
  • 28
  • 128
  • 190
Jørgen Rasmussen
  • 1,143
  • 14
  • 31
  • 5
    that means that if your component updates its value inside of an async method there could be a but where your template won't be updated. You should care about this warning if you don't understand deeply how change detection works – Andrei Jun 30 '20 at 13:24

3 Answers3

13

I agree with Andrei. It might not update your component, especially if you're getting the data from an API somewhere. To solve this, you could change the target in your tsconfig.base.json file back to es2015.

Lukho Mdingi
  • 518
  • 1
  • 5
  • 18
  • 3
    But this will stop dynamic imports to work(in case it is used) since it is supported only in es2020 – mestarted Jan 06 '21 at 07:35
  • In my case we dont use async, only promisses, can we still use es2017 target? – Rômulo Sorato Nov 06 '21 at 19:39
  • I think in the current version it's safe to set the target to newer versions. A newly generated Angular CLI project also uses target es2020 and the compiled output does not contain any async-await. So it seems as if Angular does somehow take care of down-leveling it no matter what target is set. – kai Aug 15 '22 at 09:46
5

The accepted answer is correct, but to be more specific, per this longstanding issue on GitHub, if you target es2015, your async functions will be transpiled to use a helper function called _awaiter, which uses a generator function under the hood. Because of technical constraints outlined at the above link, it is possible for Zone.js to hook the generator function and manage its execution in its own microtask queue, but it is not possible to do so for a native await statement.

The net result is that, if your function is executing in the context of Zone A, then you hit an await statement, when the next line of your function finally executes, it will be in the Root Zone. From that issue:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const test = async () => {
      console.log(Zone.current.name) // will output 'angular'
      await delay(100);
      console.log(Zone.current.name) // will output 'root'
    }

I believe that this also means that any Zone feature that allows you to manage task execution (like the Angular test helpers fakeAsync / tick / flush) will fail to correctly recognize the "task" (of waiting for the await to resolve) as pending. (Which, of course, is why this is a problem in the first place.)

Coderer
  • 25,844
  • 28
  • 99
  • 154
5

I know this issue is long resolved but I would like to leave an updated answer here and an explanation of how it works now.

With the current Angular CLI version (14.1.2) the tsconfig.json will be generated with es2020 as default. This means we can now benefit from the newest ES features and there will be no warning or problems with change detection. But how does the change detection work if the issue with async/await and zone.js is not fixed yet? I could not find any documentation about it, but I found this piece of code where Angular uses the babel transform-async-to-generator plugin to transform async/await no matter what ES target is set.

kai
  • 6,702
  • 22
  • 38