Angular - 内部与外部的ngzone逻辑 - 信号器样本

时间:2017-01-25 10:16:47

标签: angular

我在angular> = 2中有一个使用signalr的简单应用程序。我有一个问题,你理解如何确定天气将在ngzone或外部执行某些事情。如果我在这条路线上重新加载页面,下面的代码将用于所有信号器的东西在ngzone之外。如果我在另一条完全为空的路线中加载页面&从那里导航到下面的代码,它将在ngzone内执行。

import { Component, OnInit, OnDestroy, NgZone } from '@angular/core';
import { Http } from '@angular/http';
import { Subscription }    from 'rxjs/Subscription';
import { BehaviorSubject }    from 'rxjs/BehaviorSubject';

@Component({
  selector: 'app-data-page',
  templateUrl: './data-page.component.html',
  styleUrls: ['./data-page.component.less']
})
export class DataPageComponent implements OnInit {

  constructor(private http: Http) { }

  public title = 'Bug report!';
  public data = new Array<any>();

  private subscription: Subscription;
  private connection: SignalR.Hub.Connection;
  private counter:number = 1;
  private secretData = new Map<number, any>();
  private dataSubject = new BehaviorSubject(this.secretData);

  ngOnInit() {
    console.log(`ngOnInit: ${NgZone.isInAngularZone()}`);
    this.subscription = this.dataSubject.subscribe((data) => {
      console.log(`subscribe: ${NgZone.isInAngularZone()}`);
      this.data = new Array<any>();
      data.forEach((d) => {
        this.data.push(d);
      });
    }); 

    let uri = 'http://localhost:8080/fake/signalr';
    let c =  $.hubConnection(uri, { useDefaultPath: false });
    this.connection = c;
    c.logging = true;
    let hub = c.createHubProxy('myHub');
    hub.on('tick', () => {
      console.log(`tick: ${NgZone.isInAngularZone()}`);
      this.generateData();
    });
    c.start().always(() => 
    {
      console.log(`Calling getData: ${NgZone.isInAngularZone()}`);
      hub.invoke('getData')
        .always(() => {
          console.log(`getData: ${NgZone.isInAngularZone()}`);
          this.generateData();
        });
    });


    // this.http.get("http://localhost:8080/fake/api/getData").subscribe(() => {
    //   this.generateData();
    // }, (error) => {
    //   this.generateData();
    // });

    // setTimeout(() => {
    //  this.generateData();
    // }, 100);
  }



  ngOnDestroy() {    
    this.subscription.unsubscribe();
    this.connection.stop();
  }

    private generateData() {
      let end = this.counter+2;
      for(let i = this.counter; i < end; i++) {
        var d = { id: this.counter, name: "" + this.counter };
        this.secretData.set(d.id, d);
        this.counter++;
      }
      this.dataSubject.next(this.secretData);
  }
}

问题的第二部分是什么是适当的解决方案(有多种变更检测机制)?我的实际代码是服务而不是组件和我想正确的解决办法是注入一个区域&amp;在某个地方使用zone.run - 因为服务可能不应该触发gui检测更新。

示例角度前端项目: http://www.filedropper.com/angular-app

编辑运行:
npm安装
服务

编辑:
如果使用setTimeout运行创建,例如2000毫秒它会在里面。所以我想解释某种类型的计时问题。

    setTimeout(() => 
    {
// Works everything will be inside zone
        this.connect();
    }, 0);

// callbacks in the connect will be outside
    this.connect();

从上面重构连接的地方

  private connect() {
    let uri = 'http://localhost:8080/fake/signalr';
        let c =  $.hubConnection(uri, { useDefaultPath: false });
        this.connection = c;
        c.logging = true;
        let hub = c.createHubProxy('myHub');
        hub.on('tick', () => {
          console.log(`tick: ${NgZone.isInAngularZone()}`);
          this.generateData();
        });
        c.start().always(() => 
        {
          console.log(`Calling getData: ${NgZone.isInAngularZone()}`);
          hub.invoke('getData')
            .always(() => {
              console.log(`getData: ${NgZone.isInAngularZone()}`);
              this.generateData();
            });
        });
}

1 个答案:

答案 0 :(得分:2)

在Angular Zone

内运行异步操作时

当Angular Component使用计时器(setTimeout)来调用函数时,NgZone会在Angular Zone中捕获它以触发更改检测。同样,如果在Angular声明中创建一个WebSocket连接,它将在Angular Zone中捕获。

SignalR不同的时间和原因

在组件方法中同步连接SignalR不会使其在Angular Zone内运行的原因是SignalR使用真实,即非Zone d {{1}或其他一些异步通信通道,而不是在NgZone中注册的通道。

与AngularJS相似的绘图

如果您熟悉AngularJS,则相当于您的Angular Component使用window.WebSocket,而SignalR客户端本身使用的是$timeout

在Angular Zone中运行服务器推送时要小心

虽然您可以在Angular区域内运行SignalR消息,但似乎runnning every async message from a server push source (like WebSocket and SignalR) in the Angular Zone can easily result in performance issues

补充阅读

如果您想了解有关Zone.js和NgZone的更多信息,请参阅以下资源: