提问人:ServerStorm 提问时间:6/28/2023 最后编辑:ServerStorm 更新时间:6/30/2023 访问量:129
BroadcastChannel 在 setInterval 函数中丢失 .postMessage() 上下文
BroadcastChannel is losing .postMessage() context in setInterval function
问:
从 Web Worker 连接的这个计时类不保留 BroadcastChannels postMessage() 方法的上下文。使用时,它会抛出错误:
Uncaught TypeError: this.channel.postMessage is not a function
当 emit() 方法调用 postMessage() 方法时,会发生错误。签入调试器后,我可以确认注入构造函数的 this.channel 对象是有效的 BroadcastChannel 实例,并且在 emit() 方法中也有效,因为它包含 postMessage() 方法。但是,尽管有这些有效条件,仍会引发错误。
我正在使用箭头函数,因此将尊重setInterval()的父级(FoozleTimer类);但是,它似乎不起作用。this
这里是计时类,请注意 .startTimer() 和 .emit() 方法:
class FoozleTimer {
timerInterval:any;
channel:BroadcastChannel;
/**
* Construct
*/
constructor(channel:BroadcastChannel) {
this.timerInterval = null;
this.channel = channel;
}
/**
* Time interval callback function
*/
emit() {
this.channel.postMessage({countBy:1})
console.log('emit')
return '';
}
startTimer(intervalTime = 1000) {
this.timerInterval = setInterval(() => this.emit(), intervalTime);
}
stopTimer() {
clearInterval(this.timerInterval);
}
getTimer() {
return this.timerInterval;
}
}
export default FoozleTimer;
这里是调用此计时器的 Web Worker:
const channel = new BroadcastChannel('channel2');
const controls = new BroadcastChannel('controls');
// Pass the Broadcast Channel into the timer
const FT = new FoozleTimer(channel);
FT.startTimer(1000);
const timer = FT.getTimer();
controls.onmessage = (event) => {
if(event && event.data.msg == 'kill-timer') {
FT.stopTimer();
console.log('killed timer')
}
}
Web Worker 在 index.html 文件中的调用方式如下:
const worker = new Worker("./TimerWorker2.js", { type: "module" });
您能否提供任何见解,说明为什么会出现这种错误以及解决它的潜在方法?
答:
0赞
ServerStorm
6/30/2023
#1
我能够通过使用闭包而不是 emit() 方法来解决此问题。然后,我将 this 的上下文设置为参数 self,并且可以在闭包中使用它。我还将 BroadCast 通道包装到类包装器中,因此它的上下文无法更改。
下面是新的计时器类:
import { BroadcastService } from "./BroadcastService";
class FoozleTimer {
timerInterval:any;
broadcastService:BroadcastService;
/**
* Construct
*/
constructor(broadcastService:BroadcastService) {
this.timerInterval = null;
this.broadcastService = broadcastService;
}
startTimer(intervalTime = 1000) {
const self:any = this;
this.timerInterval = setInterval(function() {
self.broadcastService.postMessage({countBy:1, status:"pass"})
}, intervalTime);
}
stopTimer() {
clearInterval(this.timerInterval);
}
getTimer() {
return this.timerInterval;
}
}
export default FoozleTimer;
这是 BroadcastService:
export class BroadcastService {
broadcastChannel: BroadcastChannel;
constructor(name:string) {
this.broadcastChannel = new BroadcastChannel(name);
}
postMessage(msg:any) {
this.broadcastChannel.postMessage(msg);
}
getBroadcastChannel() {
return this.broadcastChannel;
}
}
我将尝试重构 BroadcastService,使其没有耦合的 BroadcastChannel(name),而是注入 BroadcastChannel 实例。
我希望这对其他人有所帮助
评论
setInterval(() => this.emit, intervalTime);
setInterval(() => this.emit(), intervalTime);