【问题标题】:How to use zone.js in Angular?如何在 Angular 中使用 zone.js?
【发布时间】:2019-07-28 04:26:14
【问题描述】:

我想在我的 Angular 项目中使用 zone.js(不仅仅是 runOutsideAngularZone 函数)。

我试着像这样包含它:

import { zone } from 'zone.js';

很遗憾,我收到了这个错误:

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

然后我删除了{ zone } 部分:

import 'zone.js';

但现在我得到了这个错误:

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

我的代码是这样的:

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

如果我将żone 替换为Zone,我会得到:

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

如何从 Angular 导入和使用 zone.js?

【问题讨论】:

    标签: javascript angular zone


    【解决方案1】:

    Angular 有一个名为 ngZoneZone.js 包装类。您可以像任何服务一样将其注入到您的组件中。

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

    但是,通过这种方法,我们无法使用 zone.js 的全部功能。为此,我们必须声明:

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

    此外,从 v 0.6.0 开始,API 也发生了变化。对于运行 beforeTask 和 afterTask,你可以查看它here,但是,我查看了它并找不到与 beforeTaskafterTask 相关的任何内容。

    更新
    对于运行 beforeTaskafterTask,这就是在新 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';}));
    
    }
    

    注意:
    如果您想创建一个 scheduleMicroTask 并希望在其中也具有相同的功能,那么您需要在其中实现 onInvokeTask 和/或 onScheduleTask ZoneSpec(在 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());
    }
    

    【讨论】:

    • 谢谢,但是如何使用 beforeTask 和 afterTask?也许 runGuarded 是解决方案,但是文档中函数的签名很乱(runGuarded<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T),我找不到有用的例子
    • 我想在每个任务之前和之后调用一个函数。这就是我想使用区域的原因
    • @IterAtor 我已经更新了最新 API 的答案。请记住,选择上述解决方案中的任何一个,但不要同时选择,否则您的函数/任务将被执行多次
    【解决方案2】:

    我强烈建议您将 NgZone 与 Angular 一起使用。 Documentation here

    【讨论】:

    • 谢谢,但我找不到任何可用的示例代码。如果我搜索 ngZone,我只能找到如何使用 runOutsideAngular 函数
    猜你喜欢
    • 2018-04-25
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    • 2020-04-23
    相关资源
    最近更新 更多