【发布时间】:2015-10-20 19:37:23
【问题描述】:
我正在尝试在 websocket 事件返回更新数据后更新我的视图。
我在我的应用程序中注入了一个服务,并在该服务上调用 getData() 方法。此方法向我的 NodeJS 服务器发出 socket.io 事件,该服务器又执行外部 api 调用并解析一些数据。然后,NodeJS 服务器会使用我在服务中侦听的新数据发出一个成功事件。返回成功事件后,我会更新视图中引用的服务的属性。
但是,无论我尝试什么,一旦属性更新,我都无法显示数据。
我已经搜索了几天,我发现所有的博客文章说这种变化应该是无缝的,或者我需要以某种方式合并 zone.js,或者使用表单尝试相同的逻辑(但是我试图无需用户交互即可执行此操作)。似乎没有什么对我有用,我有点沮丧。
例如:
假设我收到一个字符串数组,我想用它创建一个未排序的列表。
app.ts
import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
import {MyService} from 'js/services/MyService';
// Annotation section
@Component({
selector: 'my-app',
viewInjector: [MyService]
})
@View({
templateUrl: 'templates/my-app.tpl.html',
directives: [NgFor]
})
class MyComponent {
mySvc:MyService;
constructor(mySvc:MyService) {
this.mySvc = mySvc;
this.mySvc.getData();
}
}
bootstrap(MyComponent, [MyService]);
MyService.ts
let socket = io();
export class MyService {
someList:Array<string>;
constructor() {
this.initListeners();
}
getData() {
socket.emit('myevent', {value: 'someValue'});
}
initListeners() {
socket.on('success', (data) => {
self.someList = data;
});
}
}
我的应用程序.tpl.html
<div>
<h2>My List</h2>
<ul>
<li *ng-for="#item of mySvc.myList">Item: {{item}}</li>
</ul>
</div>
有趣的是,我发现如果我在我的组件中加入一个超时来更新我在从成功回调更新 someList 属性后在视图上设置的一些任意属性,那么两个属性值都会同时正确更新.
例如:
新的 app.ts
import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
import {MyService} from 'js/services/MyService';
// Annotation section
@Component({
selector: 'my-app',
viewInjector: [MyService]
})
@View({
templateUrl: 'templates/my-app.tpl.html',
directives: [NgFor]
})
class MyComponent {
mySvc:MyService;
num:Number;
constructor(mySvc:MyService) {
this.mySvc = mySvc;
this.mySvc.getData();
setTimeout(() => this.updateNum(), 5000);
}
updateNum() {
this.num = 123456;
}
}
bootstrap(MyComponent, [MyService]);
新的 my-app.tpl.html
<div>
<h2>My List {{num}}</h2>
<ul>
<li *ng-for="#item of mySvc.myList">Item: {{item}}</li>
</ul>
</div>
那么我应该如何让 angular2 识别在“成功”事件之后数据已更改而不更新其他属性?
使用 NgFor 指令有什么遗漏吗?
【问题讨论】:
-
如何使用 onInit() 或 onCheck()?我不清楚文档
-
我做了一个 bar bone git repo,你可以克隆它,用 socket.io github.com/jgainfort/angular2MyApp 设置一个基本的 nodejs/express 服务器。自述文件包括简单的设置过程。
-
好吧,经过多次尝试,我得出的结论是,我不知道为什么会发生这种情况,哈哈。按照您的解决方案并避免更改随机属性,您可以将
ChangeDetectorRef传递给构造函数,并在其中写入:setTimeout(() => {this.cd.requestCheck();}, 500);(其中this.cd是cd: ChangeDetectorRef,而 500 是一个足够低的数字以获得服务器和客户端发送和接收他们的事件)。我真的想要一个更好的答案,但现在我认为这可能会对你有所帮助。您可以在他们的 git 或 angular 的邮件列表中询问以获得更好的答案。 -
谢谢@ericmartinez,使用 setTimeout 的解决方法确实显示了更新的数据。我同意你的观点,这并不理想,我会采纳你的建议并将这个问题转移到有角度的问题上。我敢打赌,这与将套接字事件设置在区域之外的情况有关,因此角度永远不会捕获属性更新。