3

I would like to use zone.js in my Angular project ( not just the runOutsideAngularZone function ).

I tried to include it like this:

import { zone } from 'zone.js';

Unfortunately I get this error:

error TS2306: File 'C:/projects/MyApp/node_modules/zone.js/dist/zone.js.d.ts' is not a module.

Then I removed the { zone } part:

import 'zone.js';

But now I get this error:

error TS2552: Cannot find name 'zone'. Did you mean 'Zone'?

My code is this:

    let myZoneSpec = {
        beforeTask: function () {
            console.log('Before task');
        },
        afterTask: function () {
            console.log('After task');
        }
    };
    let myZone = zone.fork(myZoneSpec);
    myZone.run(() => {console.log('Task');});

If I replace żone with Zone, I get this:

error TS2339: Property 'fork' does not exist on type 'ZoneType'.

How could I import and use zone.js from Angular?

Iter Ator
  • 8,226
  • 20
  • 73
  • 164

2 Answers2

7

Angular has a wrapper class for Zone.js called ngZone. You can inject it into your component like any service.

    constructor(private zone: NgZone) { 
       this.zone.run(() => { console.log('This is zone'});
     }

However, with this approach, we cannot use the full functionality of zone.js. For that, we have to declare:

declare let Zone: any;
public class MyComponent {
  constructor() {
        Zone.current.fork({
            name: 'myZone'
          }).run(() => {
            console.log('in myzone? ', Zone.current.name);
          });
    }
}

Also, the APIs have changed since v 0.6.0. For running beforeTask and afterTask, you can look about it here, however, I looked into it and was unable to find anything related to beforeTask and afterTask.

Updated
For running beforeTask and afterTask, this is how it is possible in the new API.

constructor() {
    const parentZone = new Zone();
    const childZone = parentZone.fork({
      name: 'child',
      onInvoke: (...args) => { 
                 console.log('invoked\n', args);
                 const valueToReturn = args[3](); // Run the function provided in the Zone.run
                 console.log('after callback is run');
                 return valueToReturn;
              }
    });
   console.log(childZone.run(() => {console.log('from run'); return 'from child run';}));

}

NOTE:
If you want to create a scheduleMicroTask and want to have same functionality in it also, then you will need to implement onInvokeTask and/or onScheduleTask in the ZoneSpec (inside the parentZone.fork()).

constructor() {
   const parentZone = new Zone();
    const childZone = parentZone.fork({
      name: 'child',
      onScheduleTask: (...args) => {
        console.log('task schedule...\n', args);
        return args[3];
      },
      onInvokeTask: (...args) => {
        console.log('task invoke...\n', args);
        return args[3].callback();
      }
    });

    const microTask = childZone
                      .scheduleMicroTask(
                        'myAwesomeMicroTask',
                        () => { 
                                console.log('microTask is running'); 
                                return 'value returned from microTask'; 
                            } );
    console.log(microTask.invoke());
}
Shadab Faiz
  • 2,380
  • 1
  • 18
  • 28
  • Thank you, but how to use beforeTask and afterTask? Maybe runGuarded is the solution, but the signature of the function in the docs is messy (`runGuarded(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T`), and I am not able to find useful examples – Iter Ator Jun 03 '19 at 15:49
  • I would like to call a function before and after each task. That's why I would like to use zones – Iter Ator Jun 03 '19 at 16:35
  • @IterAtor I have updated the answer for the latest API. Just remember, choose either of the mentioned solutions but not both otherwise, your function/task will be executed multiple times – Shadab Faiz Jun 03 '19 at 19:11
-1

I Highly recommend you to use NgZone with Angular. Documentation here

ilyas shabi
  • 194
  • 1
  • 7
  • Thank you, but I am not able to find any usable example code. If I search for ngZone, all I can find is how to use the runOutsideAngular function – Iter Ator Jun 03 '19 at 15:43