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