Angular --- 如何重置 Websocket 消息的倒数计时器?
Angular --- How to reset countdown timer on Websocket message?
我使用了这个例子中的倒数计时器解决方案:Stackblitz --- It is from accepted answer of this
不同之处在于我不使用 html 输入来重置我的计时器,而是使用这样的 Websocket 消息(不同之处在于开关):
转-timer.directive.ts:
@Directive({
selector: '[counter]'
})
export class CounterDirective implements OnChanges, OnDestroy {
private counter$ = new Subject<any>();
private countSub$: SubscriptionLike;
@Input() counter: number;
@Input() interval: number;
@Output() value = new EventEmitter<number>();
constructor(private client: ClientService)
{
this.countSub$ = this.counter$.pipe(
switchMap((options: any) =>
timer(0, options.interval).pipe(
take(options.count),
tap(() => this.value.emit(--options.count))
)
)
).subscribe();
this.client.messages.subscribe(msg =>
{
switch (msg.SUBJECT)
{
case 'TT_UPDATE':
{
this.counter = msg.COUNTER;
}
break;
default:
break;
}
});
}
ngOnChanges() {
this.counter$.next({ count: this.counter, interval: this.interval });
}
ngOnDestroy() {
this.countSub$.unsubscribe();
}
}
那根本没有重置计时器,所以我尝试将消息发送到初始组件,但仅在第一次发送时才重置计时器。
转-timer.component.ts:
@Component({
selector: 'app-turn-timer',
templateUrl: './turn-timer.component.html',
styleUrls: ['../../../../angry_styles.css']
})
export class TurnTimerComponent implements OnInit
{
public counter : number = 60;
interval = 1000;
public current_player: string;
constructor (private ll: LL, private client: ClientService, private players: PlayersInfo)
{
this.client.messages.subscribe(msg =>
{
switch (msg.SUBJECT)
{
case 'TT_UPDATE':
{
this.counter = msg.COUNTER;
this.current_player = msg.PLAYER_ON_TURN;
}
break;
default:
break;
}
});
}
ngOnInit(): void {}
}
有html:
<ng-container [counter]="counter" [interval]="interval" (value)="value = $event">
<span>{{ value }}</span>
</ng-container>
答案原作者有
<input type="number" [(ngModel)]="counter"/>
在他的html和这个
的每次值
<input>
已更改,倒数计时器已重置为该值。但是在我的应用程序中,它应该由发送 Websocket 消息的 C# 服务器重置。
那么我期望的结果是什么: 在每个 "TT_UPDATE" 消息中,我希望 HTML 中的 {{ value }} 更改为 msg.COUNTER。 this.counter$.pipe 然后递减 {{value}}。那工作正常。只是重置部分不起作用。
顺便说一句。每条消息都被成功接收,我检查了字段的名称。这是消息的定义:
export interface Message {
SUBJECT: string;
COUNTER?: number; // This is the problematic field.
PLAYER_ON_TURN?: string;
}
@Injectable()
export class ClientService
{
public messages: Subject < Message > ;
constructor(wsService: WebsocketService) {
this.messages = < Subject < Message >> wsService
.connect(CHAT_URL).pipe(
map((response: MessageEvent): Message => {
console.log(response);
const data = JSON.parse(response.data);
return data;
}), share());
}
我从代码中删除了导入和路径,因此它更短但它们是正确的。在浏览器控制台中也没有发现错误。
最后,我自己找到了解决办法。为此,我什至不需要 this.counter。我修改了收到消息后的情况:
this.client.messages.subscribe(msg =>
{
switch (msg.SUBJECT)
{
case 'TT_UPDATE':
{
this.ResetTimer(msg.COUNTER); // THIS IS NEW !!!
}
break;
default:
break;
}
});
}
然后我创建了一个新方法,将倒数计时器重置为从消息中收到的值:
ResetTimer(updatedValue: number)
{
this.counter$.next({ count: updatedValue, interval: this.interval });
}
因为我不改变间隔,所以我让它保持不变。有时我想知道事情是多么容易。
我使用了这个例子中的倒数计时器解决方案:Stackblitz --- It is from accepted answer of this
不同之处在于我不使用 html 输入来重置我的计时器,而是使用这样的 Websocket 消息(不同之处在于开关):
转-timer.directive.ts:
@Directive({
selector: '[counter]'
})
export class CounterDirective implements OnChanges, OnDestroy {
private counter$ = new Subject<any>();
private countSub$: SubscriptionLike;
@Input() counter: number;
@Input() interval: number;
@Output() value = new EventEmitter<number>();
constructor(private client: ClientService)
{
this.countSub$ = this.counter$.pipe(
switchMap((options: any) =>
timer(0, options.interval).pipe(
take(options.count),
tap(() => this.value.emit(--options.count))
)
)
).subscribe();
this.client.messages.subscribe(msg =>
{
switch (msg.SUBJECT)
{
case 'TT_UPDATE':
{
this.counter = msg.COUNTER;
}
break;
default:
break;
}
});
}
ngOnChanges() {
this.counter$.next({ count: this.counter, interval: this.interval });
}
ngOnDestroy() {
this.countSub$.unsubscribe();
}
}
那根本没有重置计时器,所以我尝试将消息发送到初始组件,但仅在第一次发送时才重置计时器。
转-timer.component.ts:
@Component({
selector: 'app-turn-timer',
templateUrl: './turn-timer.component.html',
styleUrls: ['../../../../angry_styles.css']
})
export class TurnTimerComponent implements OnInit
{
public counter : number = 60;
interval = 1000;
public current_player: string;
constructor (private ll: LL, private client: ClientService, private players: PlayersInfo)
{
this.client.messages.subscribe(msg =>
{
switch (msg.SUBJECT)
{
case 'TT_UPDATE':
{
this.counter = msg.COUNTER;
this.current_player = msg.PLAYER_ON_TURN;
}
break;
default:
break;
}
});
}
ngOnInit(): void {}
}
有html:
<ng-container [counter]="counter" [interval]="interval" (value)="value = $event">
<span>{{ value }}</span>
</ng-container>
答案原作者有
<input type="number" [(ngModel)]="counter"/>
在他的html和这个
的每次值<input>
已更改,倒数计时器已重置为该值。但是在我的应用程序中,它应该由发送 Websocket 消息的 C# 服务器重置。
那么我期望的结果是什么: 在每个 "TT_UPDATE" 消息中,我希望 HTML 中的 {{ value }} 更改为 msg.COUNTER。 this.counter$.pipe 然后递减 {{value}}。那工作正常。只是重置部分不起作用。
顺便说一句。每条消息都被成功接收,我检查了字段的名称。这是消息的定义:
export interface Message {
SUBJECT: string;
COUNTER?: number; // This is the problematic field.
PLAYER_ON_TURN?: string;
}
@Injectable()
export class ClientService
{
public messages: Subject < Message > ;
constructor(wsService: WebsocketService) {
this.messages = < Subject < Message >> wsService
.connect(CHAT_URL).pipe(
map((response: MessageEvent): Message => {
console.log(response);
const data = JSON.parse(response.data);
return data;
}), share());
}
我从代码中删除了导入和路径,因此它更短但它们是正确的。在浏览器控制台中也没有发现错误。
最后,我自己找到了解决办法。为此,我什至不需要 this.counter。我修改了收到消息后的情况:
this.client.messages.subscribe(msg =>
{
switch (msg.SUBJECT)
{
case 'TT_UPDATE':
{
this.ResetTimer(msg.COUNTER); // THIS IS NEW !!!
}
break;
default:
break;
}
});
}
然后我创建了一个新方法,将倒数计时器重置为从消息中收到的值:
ResetTimer(updatedValue: number)
{
this.counter$.next({ count: updatedValue, interval: this.interval });
}
因为我不改变间隔,所以我让它保持不变。有时我想知道事情是多么容易。