我正在嘗試從用 swift vapor 撰寫的 Web 套接字獲取和更新前端 Angular 應用程式中的資料。后端也是我寫的,所以我可以編輯任何東西。當前端第一次連接時,套接字發送所有需要的資料(在這種情況下,一個大的 JSON 物件包含子物件,而子物件又具有子物件等......)。
{
"alpha": {
"isUsingXXX": true,
"loopbacks": [
"10.50.255.1",
"10.50.255.11"
],
"hasLte": false,
"isUsingLte": false,
"virtualLink": {
"links": {
"Bravo <-> XXX": {
"gradeUpdates": {
"up": {
"174": {
"message": "Test message",
"grade": "BAD",
"progressive": 174,
"date": "2022-11-03T08:13:54Z"
}
},
"down": {
"175": {
"message": "Test message",
"grade": "BAD",
"progressive": 175,
"date": "2022-11-03T08:13:54Z"
}
}
},
"congestionUpdates": {
"173": {
"message": "Test message",
"congestion": "CONGESTED",
"progressive": 173,
"date": "2022-11-03T08:13:54Z"
}
},
"statusUpdates": {
"7": {
"status": "ACTIVE",
"message": "Setting initial value",
"progressive": 7,
"date": "2022-11-03T08:13:54Z"
}
},
"name": "Bravo <-> XXX"
},
"Alpha <-> XXX": {
"gradeUpdates": {
"up": {
"170": {
"message": "Test message",
"grade": "GOOD",
"progressive": 170,
"date": "2022-11-03T08:13:54Z"
}
},
"down": {
"171": {
"message": "Test message",
"grade": "GOOD",
"progressive": 171,
"date": "2022-11-03T08:13:54Z"
}
}
},
"congestionUpdates": {
"4": {
"message": "Setting initial value",
"congestion": "UNCONGESTED",
"progressive": 4,
"date": "2022-11-03T08:13:54Z"
}
},
"statusUpdates": {
"3": {
"status": "ACTIVE",
"message": "Setting initial value",
"progressive": 3,
"date": "2022-11-03T08:13:54Z"
}
},
"name": "Alpha <-> XXX"
}
},
"gradeUpdates": {
"176": {
"message": "Test message",
"grade": "BAD",
"progressive": 176,
"date": "2022-11-03T08:13:54Z"
}
}
},
"statusUpdates": {
"1667463234643": {
"status": "SAILING",
"date": "2022-11-03T08:13:54Z"
}
},
"pings": {
"1667463234643": {
"latency": 675,
"date": "2022-11-03T08:13:54Z"
}
},
"hasXXX": true,
"name": "Alpha",
"codename": "alpha"
},
"bravo":{...},
"charlie":{...}
}
現在,我想要實作的是使用后續套接字訊息更新單個子物件,這些訊息類似于
{
"kind":"linkGradeUpdate",
"codename": "alpha",
"linkName": "Bravo <-> SantaRosa 107",
"direction": "up",
"data":{
"201": {
"message": "Update test message",
"grade": "GOOD",
"progressive": 201,
"date": "2022-11-03T08:15:54Z"
}
}
}
我的意思是我試圖發送只需要的資料來執行更新,將它們添加到主要接收的大物件中。我的代碼中的所有內容都可以正常作業,除了我無法弄清楚的 UI。我試圖制作一個組件,它通過子組件回圈資料,但我無法顯示資料,我需要一個Observable嗎?
import { Injectable } from '@angular/core'
import { Ship, Message } from '../interfaces'
@Injectable({
providedIn: 'root'
})
export class WebsocketService {
url = 'ws://localhost:8080/api/socket/session'
socket: WebSocket
ships: Map<string, Ship> = new Map()
constructor() {}
openSocket() {
this.socket = new WebSocket(this.url)
this.socket.onopen = event => {
console.log(`Open ${event}`)
}
this.socket.onmessage = event => {
const message = JSON.parse(event.data)
if (this.ships.size == 0) {
console.log('Inititalizing ships...')
this.ships = new Map(Object.entries(message))
} else {
console.log('Updating ship...')
this.updateShips(message)
}
}
this.socket.onclose = event => {
console.log(`Closed ${event}`)
}
}
updateShips(message: Message) {
let ship: Ship = this.ships.get(message.shipCodename)
const data = message[message.kind]
const linkName = message.linkName
switch (message.kind) {
case 'shipStatus':
console.log('Before update')
ship.statusUpdates[data.progressive] = data
console.log('After update')
break
case 'virtualLinkGrade':
ship.virtualLink.gradeUpdates[data.progressive] = data
break
case 'linkGrade':
const linkDirection = message.linkDirection
if (linkDirection == 'UP') {
ship.virtualLink.links[linkName].gradeUpdates.up[data.progressive] = data
} else {
ship.virtualLink.links[linkName].gradeUpdates.down[data.progressive] = data
}
break
case 'linkStatus':
ship.virtualLink.links[linkName].statusUpdates[data.progressive] = data
break
case 'linkCongestion':
ship.virtualLink.links[linkName].congestionUpdates[data.progressive] = data
break
}
}
closeSocket() {
this.socket.close()
}
}
import { Component, OnInit } from '@angular/core'
import { WebsocketService } from 'src/app/services/websocket.service'
import { Ship } from 'src/app/interfaces'
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.page.html',
styleUrls: ['./dashboard.page.scss']
})
export class DashboardPage implements OnInit {
ships: Map<string, Ship>
constructor(private websocket: WebsocketService) {}
ngOnInit() {
this.websocket.openSocket()
this.ships = this.websocket.ships
console.log(this.ships)
}
ngOnDestroy() {
this.websocket.closeSocket()
}
}
現在,我知道資料是在 ngOnInit() 之后更新的,所以我可以在控制臺中看到資料,但在渲染視圖中看不到。我的問題是:我需要Observable<Map<string, Ship>>, 還是Map<string, Observable<Ship>>重新渲染剛剛更新的資料塊?或者可能是完全不同的東西......謝謝,我希望我已經足夠清楚......
uj5u.com熱心網友回復:
在您的服務中,您正在重新分配ships屬性: ,但您只能在使用它的組件的函式中this.ships = new Map(Object.entries(message))獲取該屬性的內容一次。ngOnInit
為了確保您的組件可以獲取更新的船舶資料,您可以使該ships屬性具有一個型別Subject(類似于Observable),然后在您的組件中訂閱它。以下是一些應該為您指明正確方向的代碼:
服務
export class WebsocketService {
ships: Subject<Map<string, Ship>> = new Subject();
private shipData: Map<string, Ship> = new Map<string, Ship>();
constructor() {}
openSocket() {
// ...
this.socket.onmessage = event => {
const message = JSON.parse(event.data)
if (this.ships.size == 0) {
console.log('Inititalizing ships...')
this.shipData = new Map(Object.entries(message));
this.ships.next(this.shipData);
// ^^^^ <= key part
} else {
console.log('Updating ship...')
this.updateShips(message)
}
}
}
updateShips(message: Message) {
let ship: Ship = this.shipData.get(message.shipCodename)
// ...
this.ships.next(this.shipData);
}
}
注意:要使該updateShips方法起作用,我們需要在服務中存盤最后一次發貨資料的副本,并在更改時通過主題發送。
零件
ships: Map<string, Ship>
shipsSubscription: Subscription;
constructor(private websocket: WebsocketService) {}
ngOnInit() {
this.websocket.openSocket()
this.shipsSubscription = this.websocket.ships.subscribe(ships => {
this.ships = ships;
console.log(this.ships)
});
}
ngOnDestroy() {
this.websocket.closeSocket()
// It's a good idea to remove subscriptions when the component is destroyed
if (this.shipsSubscription) {
this.shipsSubscription.unsubscribe();
}
}
這將確保您的組件在從服務器發送時獲取最新的船舶資料。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/529110.html
