每次收到来自WebSocket的消息时,我都会尝试更新totalRequests
,payloadSize
,payloadSizeType
属性。这项工作成功,我可以通过console.log
确认,因为它们会根据从服务器发送的内容正确更新每个日志。
问题是我的模板由于某种原因没有更新以反映这些更改。
我可以确认没有其他潜在的错误,因为当我创建一个测试函数并在点击时更新这些值时,它们会更新并且更改确实会反映在模板中,因此我得出结论,错误必定即将到来从我传递WS回调的方式...除非有其他我不知道的东西。
import { Component, OnInit } from '@angular/core';
import { AttackService } from './attack.service';
import { WebSocketService } from '../../../lib/service/websocket/websocket.service';
import { WebSocketConfig } from '../../../lib/service/websocket/websocket.config';
@Component({
selector: 'attack',
templateUrl: './attack.component.html',
styleUrls: ['./attack.component.css'],
providers: [AttackService, WebSocketService]
})
export class AttackComponent implements OnInit {
private model: Object = {
url: "http://localhost",
kb_per_request: 5,
duration: 5
};
private hasReceivedMessage: boolean = false;
private totalRequests: number = 0;
private payloadSize: number = 0;
private payloadSizeType: string = 'KB';
constructor(private attackService: AttackService, private socket: WebSocketService) {}
ngOnInit(): void {
this.socket.create(new WebSocketConfig(this.sOnOpen, this.sOnClose, this.sOnMessage, this.sOnError));
}
sOnOpen(): void {
console.log('WebSocket connection successfully established.');
}
sOnClose(code: number): void {
console.log(`WebSocket connection closed (${code}).`);
}
sOnMessage(data: any): void {
this.hasReceivedMessage = true;
this.totalRequests = data.total_requests;
this.payloadSize = data.payload_size;
this.payloadSizeType = data.payload_size_type;
console.log('====================================');
console.log('Total requests: ', this.totalRequests);
console.log('Payload size: ', this.payloadSize);
console.log('Payload type: ', this.payloadSizeType);
}
sOnError(data: any): void {
console.log('WebSocket error occurred: ', data);
}
submit(): void {
this.attackService.attack(this.model).subscribe(
res => {
let data = res.json();
if (data.success) {
console.log(data.message);
}
},
err => {
console.log('Error:', err);
}
);
}
}
我以为我使用错误的this
上下文传递方法,但即使绑定正确的上下文,模板仍然不会更新以反映更改。
constructor(private attackService: AttackService, private socket: WebSocketService) {
this.sOnOpen = this.sOnOpen.bind(this);
this.sOnClose = this.sOnClose.bind(this);
this.sOnMessage = this.sOnMessage.bind(this);
this.sOnError = this.sOnError.bind(this);
}
任何人都知道这个问题的解决方案吗?
更新
WebSocketService:
import { Injectable } from '@angular/core';
import { WebSocketConfig } from './websocket.config';
@Injectable()
export class WebSocketService {
private socket = null;
private uri = "ws://localhost:80/ws";
create(config: WebSocketConfig): void {
window.onload = () => {
this.socket = new WebSocket(this.uri);
this.socket.onopen = config.onOpen;
this.socket.onclose = config.onClose;
this.socket.onmessage = res => config.onMessage(JSON.parse(res.data));
this.socket.onerror = config.onError;
};
}
send(data: any): void {
this.socket.send(data);
}
}
答案 0 :(得分:1)
实际上,它确实看起来像是一个背景问题。您是否尝试过以下方法:
exact={true}
修改强> 老实说,我正在拍摄这张照片。但也许可以将此方法更改为在config上绑定:
<Router>
<Route path='/' exact={true} component={A} />
<Route path='/A' exact={true} component={A} />
<Route path='/B' exact={true} component={B} />
</Router>
答案 1 :(得分:1)
尝试更新您的sOnMessage方法以将其自身包装在setTimeout中。
sOnMessage(data: any): void {
setTimeout(() => {
this.hasReceivedMessage = true;
this.totalRequests = data.total_requests;
this.payloadSize = data.payload_size;
this.payloadSizeType = data.payload_size_type;
console.log('====================================');
console.log('Total requests: ', this.totalRequests);
console.log('Payload size: ', this.payloadSize);
console.log('Payload type: ', this.payloadSizeType);
}, 1);
}
如果可行,那么您在用户界面中看不到更新的原因是因为当您的Web套接字收到值时,未正确触发更改检测。 Angular的更改检测通过使用Zone.js来工作,Zone.js包装所有异步行为,以便每次异步函数完成时都可以通知Angular。如果setTimeout有效,那么Zone.js没有正确捕获websocket异步行为。
通过使用NgZone服务有更优雅的方法来解决问题,但是setTimeout可以快速修复。
答案 2 :(得分:1)
我对此的解决方案并不完全是两个答案所提供的,但他们指出了我正确的方向。
首先,我在AttackComponent中创建了我的websocket连接,我宁愿在我的AppComponent中创建它,以便可以全局访问连接(与我的问题无关)。
我创建了一个间隔函数来检查套接字是否已连接,如果是,则调用一个函数调用,这是一个我从AttackComponent传入的回调函数。
该回调是通过AttackComponent中的箭头函数传递的,这为我提供了正确的this
上下文。然后我调用另一个方法将套接字onmessage
属性设置为我的AttackComponent方法,并将其绑定到箭头函数允许的正确this
上下文。我也可以在那之外完成绑定。
以下是我所做的示例,现在可以正常运行并更新我的模板:
WebSocketService:
setSocketOnMessage(fn: Function): void {
this.socket.onmessage = function (message) {
fn(JSON.parse(message.data), message);
};
}
onReady(cb: Function): void {
let socketInterval = setInterval(() => {
if (this.isConnected()) {
cb();
clearInterval(socketInterval);
}
}, 50);
}
AttackComponent:
constructor(private webSocketService: WebSocketService) {
this.webSocketService.onReady(() => {
this.webSocketService.setSocketOnMessage(this.sOnMessage.bind(this));
});
}
sOnMessage(data: any): void {
this.hasReceivedMessage = true;
this.totalRequests = data.total_requests;
this.payloadSize = data.payload_size;
this.payloadSizeType = data.payload_size_type;
}
答案 3 :(得分:0)
我有类似的问题。在我的情况下,websocket注入组件,因此它可能不是相同的解决方案。基本上我使用了这里描述的方法(https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html#observables)
this.socket$.subscribe( (message: Message) => {
this.messages.push(message);
this.cd.markForCheck(); // mark the path from our component until root to be checked for the next change detection run.
}
然后当我收到消息时......
print(String(bytes: jsonData, encoding: String.Encoding.utf8))
希望这有帮助