使用来自Web套接字的数据更新视图 - Angular 5

时间:2018-04-23 21:36:52

标签: angular websocket

我有一个页面,它在页面加载时接收一组数据,并使用*ngFor指令显示它。还有一个连接到Web Socket以接收更新的数据。在这个例子中,它是乘船游览的时间表。我的问题是我不确定如何使用来自WS的新数据更新页面加载数据。到目前为止,我有这段代码:

timeTableService.service.ts - 获取页面加载初始数据的服务

import { Injectable } from '@angular/core';
import { ApiService } from './api.service';

@Injectable()
export class TimeTableService {

    constructor(
        private apiService: ApiService,
    ) { }

    getInitialTimes() {
        return this.apiService.get('/timetable/')
    }
}

liveTimeTableService.service.ts - 使用this library连接处理Web套接字连接的服务

import { Injectable } from '@angular/core'
import { QueueingSubject } from 'queueing-subject'
import { Observable } from 'rxjs/Observable'
import websocketConnect from 'rxjs-websockets'
import 'rxjs/add/operator/share'

@Injectable()
export class LiveTimeTableService {
    private inputStream: QueueingSubject<any>
    public messages: Observable<any>

    public connect() {
        this.messages = websocketConnect(
            'ws://www.timetables.com:8080',
            this.inputStream = new QueueingSubject<string>() 
        ).messages.share()
    }
    public send(message: string):void {
        this.inputStream.next(message)
    }
}

timeTable.component.ts - 显示时间表的组件

import { Component, OnInit } from '@angular/core';
import { TimeTableService, LiveTimeTableService } from './shared';
import { Subscription } from 'rxjs/Subscription'

@Component({
    selector: 'app-time-table',
    templateUrl: './time-table.component.html',
})

export class TimeTableComponent implements OnInit {
    private timeTable: any;
    private socketSubscription: Subscription

    constructor(
        private timeTableService: TimeTableService,
        private liveTimeTableService: LiveTimeTableService,
    ) {}

    ngOnInit() {
        this.liveTimeTableService.connect();
        this.liveTimeTableService.send('SUBSCRIBE times')

        // subscribe to any message updates
        this.socketSubscription = this.liveTimeTableService.messages
            .subscribe((timesUpdate) => {
                this.timeTable = timesUpdate;
        })

        // get the time table data on page load
        this.timeTableService.getInitialTimes()
            .subscribe((timeTable) => {
                this.timeTable = timeTable
        })
    }

    ngOnDestroy() {
        this.socketSubscription.unsubscribe()
    }
}

HTML模板

<div *ngFor="let boat of timeTable">
    {{ boat.name }}
    <span *ngFor="let time of boat.times">{{time}}</span>
</ldiv>

数据看起来像这样

Page load data

WS Message data(包含时间和状态等次要更新):

问题是每次来自WS的新消息都会重置this.timeTable,并且整个*ngFor指令再次运行并重建dom。我想要做的是使用WS消息中的新值更新*ngFor中的任何'time'表达式,然后应用css类来通知用户更改:

enter image description here

任何建议或建议如何激活这一点将不胜感激。并为很长的帖子道歉!

1 个答案:

答案 0 :(得分:0)

也许使用trackBy选项,就像在这个答案中一样:

Angular 2 - with ngFor, is it possible to update values without rebuilding the dom?

因此,您的代码将类似于:

查看:

<div *ngFor="let boat of timeTable; let i = index; trackBy: trackByFn">
    {{ boat.name }}
    <span *ngFor="let time of boat.times">{{time}}</span>
</div>

<强>组件

trackByFn(index, item) {
  return index;
}

作为参考,您应该使用:https://angular.io/guide/template-syntax#ngfor-with-trackby