Angular 角区逻辑用于内部与外部信号器采样

Angular 角区逻辑用于内部与外部信号器采样,angular,Angular,我在angular>=2中有一个使用Signal的简单应用程序。我有一个问题,你不知道如何确定某些事情将在ngzone内部还是外部执行。如果我在这条路线上重新加载页面,下面的代码将在ngzone之外。若我在另一条完全为空的路径中加载页面&从那个里导航到下面的代码,它将在ngzone内执行 import { Component, OnInit, OnDestroy, NgZone } from '@angular/core'; import { Http } from '@angular/http

我在angular>=2中有一个使用Signal的简单应用程序。我有一个问题,你不知道如何确定某些事情将在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);
  }
}
其中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();
            });
        });
}
在角度区域内运行异步操作时 当您的角度组件使用计时器(
setTimeout
)调用函数时,
NgZone
会在角度区域捕获该函数以触发更改检测。同样,如果在Angular declarable中创建WebSocket连接,它将在Angular区域中捕获

信号器不同的时间和原因 在组件方法中同步连接信号器不会使其在角度区域内运行的原因是信号器使用的是,即非
区域
d
窗口。WebSocket
或其他一些异步通信信道,而不是在NgZone中注册的信道

绘制与AngularJS平行的图形 如果您熟悉AngularJS,那么与您的示例相同的是,您的Angular组件正在使用
$timeout
,而SignalR客户端本身正在使用本机
setTimeout

在角度区域运行服务器推送时要小心 虽然您可以在角度区域内运行信号器消息,但似乎是这样

补充阅读 如果您想了解更多关于Zone.js和NgZone的信息,以下是一些有价值的资源:

  • 蒂亚戈·罗尔道
  • 在角API文档中
  • 由Max“NGK向导”编写
  • 彼得·默茨
  • 在Zone.js

默认情况下,由Angular触发的任何代码都会在Angular zone中执行。你的问题不是很清楚。你能把你的代码减少到最小并创建一个plnkr来发现问题吗?你如何在plnkr中包含signalr?但它不包括信号器后端只是前端有什么想法吗?方法位于区域中,使用setTimeout进行调度会使其回调变为位于区域中,否则不会。或者链接到文档,描述当你在区域之外时的情况——看到了angular doc&优秀文章中链接的brians视频,但没有给出任何警告或信息来解释这一点。
  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();
            });
        });
}