typescript - Observable.interval 的问题 - 模板中的数据未更新,ngFor 的长度不正确,启动时获取轮询数据

标签 typescript angular observable rxjs

在我不断努力自学 Angular2 的过程中(下次我有假期我要去度假!)我遇到了一个问题......我有一个从我创建的虚假 REST 服务中提取用户数据的服务.在我的服务中,我希望轮询数据(在这种情况下,我模拟在线的 friend 和不在线的 friend )。这是带有轮询代码的服务:

@Injectable()
export class UserDataService {

    public loginInUser: Subject<UserStatus> = new BehaviorSubject<UserStatus>(null);
    public currentUser: UserStatus;
    public onlineContacts: Subject<UserContact> = new BehaviorSubject<UserContact>(null);
    public userContacts: Subject<UserContact> = new BehaviorSubject<UserContact>(null);

    constructor(public http:Http) {
        this.loadUserStatus(); // this is lower in the Component... I have not included it here
        this.pollContacts();
    }

    private pollContacts() : any {

        var headers = new Headers();
        headers.append('Content-Type', 'application/json');

        return Observable.interval(30000)
            .switchMap(() => this.http.get('/restservice/contacts', {headers: headers}))
            //.startWith() - Would this allow me to kick off the service when the Component is loaded / called?
            .subscribe((data: any) => {
                data = data.json();
                this.onlineContacts.next(data.onlineContacts);
                this.userContacts.next(data.allContacts);
            });

    }

这是我调用服务的组件:

@Component({
    selector: 'contacts-list',
    directives: [...ROUTER_DIRECTIVES],
    template: require('./contact-list.html')
})

export class ContactsList {

    public onlineContacts: any;
    public userContacts: any;

    constructor (public userDataService: UserDataService) {
        this.userDataService.onlineContacts.subscribe(
            (onlineContacts) => {
                this.onlineContacts = onlineContacts;
            });

        this.userDataService.userContacts.subscribe(
            (userContacts) => {
                this.userContacts = userContacts;
            });
    }
}

这是我的组件的 HTML View /模板...

<h3>Online Contacts</h3>
<div class="online-contact" *ngIf="onlineContacts?.length > 0" *ngFor="#con of onlineContacts" [routerLink]="['ForeignProfile', {id: con.persId}]">
    <img [src]="con.imgUrl" class="img-circle online-contact-img">
    {{ con.name }}
</div>

<h3>Contacts</h3>
<div class="online-contact" *ngIf="userContacts?.length > 0" *ngFor="#con of userContacts" [routerLink]="['ForeignProfile', {id: con.persId}]">
    <img [src]="con.imgUrl" class="img-circle offline-contact-img">
    {{ con.name }}
</div>

现在我被问题困扰了......

  1. 首先,我需要在加载组件/ View 时启动 pollContacts() 方法,而不是等待时间间隔过去。我尝试添加 .startWith 方法(请参阅评论)但我不确定要传递给该方法的参数?

  2. 轮询有效并且正确的信息从服务传递到组件...但是模板没有更新?我是否需要将 async 管道添加到模板中(我确实尝试过但没有成功)?

  3. 出于某种原因,两个 ngFor 指令迭代(或循环)比对象数组的实际长度多一个。例如,当对象数组仅包含一项时,*ngFor="#con of onlineContacts" 有两行(循环两次),而 *ngFor="#con of userContacts" 当 userContacts 的长度为 19 时,有 20 行(循环 20 次)!

我意识到我已经并且一直在问很多关于这个主题的问题,但我没有人可以就这个主题交谈,所以请容忍我的问题。提前致谢。

最佳答案

我认为您需要明确通知 Angular 有关更改:

@Component({
    selector: 'contacts-list',
    directives: [...ROUTER_DIRECTIVES],
    template: require('./contact-list.html'),
    changeDetection: ChangeDetectionStrategy.OnPush // <== added (optional)
})

export class ContactsList {

    public onlineContacts: any;
    public userContacts: any;

    constructor (public userDataService: UserDataService,
        private cd: ChangeDetectorRef // <== added
    ) {
        this.userDataService.onlineContacts.subscribe(
            (onlineContacts) => {
                this.onlineContacts = onlineContacts;
                this.cd.markForCheck(); // <== added
            });

        this.userDataService.userContacts.subscribe(
            (userContacts) => {
                this.userContacts = userContacts;
                this.cd.markForCheck(); // <== added
            });
    }
}

另见 http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

关于typescript - Observable.interval 的问题 - 模板中的数据未更新,ngFor 的长度不正确,启动时获取轮询数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35599714/

相关文章:

javascript - RxJs 允许前 n 个请求然后延迟

Angular 删除所有查询参数

angular - 如何避免嵌套 rxJS 订阅

angular - 以 Angular 2 对动画进行无限反击

css - 如何从 Angular 垫菜单中删除选择框?

angular - 在 Angular CLI 应用程序中使用 vtk.js/glsl 文件

angular - 声明 FormBuilder 的库 (@angular/forms) 未被 ngcc 正确处理

javascript - 在对象的嵌套数组中搜索字符串并设置 IsCheckedIn flag = true;

java - RxJava。运营商在哪里?

angular - 如何创建在验证后返回 Observable 的函数?