首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >内部与外部信号采样的角度- ngzone逻辑

内部与外部信号采样的角度- ngzone逻辑
EN

Stack Overflow用户
提问于 2017-01-25 10:16:46
回答 1查看 1.8K关注 0票数 2

我在>= 2中有一个简单的应用程序,它使用signalr。我有一个问题,你不知道如何确定是否某些东西将在内或外执行。如果我在此路径上重新加载页面,下面的代码将用于所有signalr内容在ngzone之外。如果我在另一个完全为空的路由中加载页面&从那里导航到下面的代码,它将在ngzone中执行。

代码语言:javascript
复制
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);
  }
}

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

样本角前沿项目:http://www.filedropper.com/angular-app

编辑以运行:

npm安装

吴服务

编辑:

如果使用setTimeout (例如2000 ms )运行创建,它将在其中。所以我想解释的是一些时间问题。

代码语言:javascript
复制
    setTimeout(() => 
    {
// Works everything will be inside zone
        this.connect();
    }, 0);

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

连接是从上面重构出来的

代码语言:javascript
复制
  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();
            });
        });
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-28 18:31:51

当异步操作在角区域内运行时

当您的角度组件使用计时器(setTimeout)调用函数时,NgZone会在角区域中捕获它以触发更改检测。同样,如果您在角声明内建立了一个WebSocket连接,那么它将在角区域中捕获。

何时和为什么SignalR是不同的

在组件方法中同步连接SignalR的原因并不使它在角区域内运行,原因是SignalR使用的是real,即非Zoned window.WebSocket或其他异步通信通道,而不是在NgZone中注册的信道。

绘制与AngularJS的平行图

如果您熟悉AngularJS,那么与您的示例相当的是,您的角度组件使用的是$timeout,而SignalR客户端本身使用的是本机setTimeout

运行服务器时要小心,在角度区域内推送服务器。

虽然您可以在角区域内运行SignalR消息,但似乎运行角区域中来自服务器推送源(如WebSocket和SignalR)的每条异步消息很容易导致性能问题

附加读数

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41848898

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档