BroadcastChannel 在 setInterval 函数中丢失 .postMessage() 上下文

BroadcastChannel is losing .postMessage() context in setInterval function

提问人:ServerStorm 提问时间:6/28/2023 最后编辑:ServerStorm 更新时间:6/30/2023 访问量:129

问:

从 Web Worker 连接的这个计时类不保留 BroadcastChannels postMessage() 方法的上下文。使用时,它会抛出错误:

Uncaught TypeError: this.channel.postMessage is not a function

当 emit() 方法调用 postMessage() 方法时,会发生错误。签入调试器后,我可以确认注入构造函数的 this.channel 对象是有效的 BroadcastChannel 实例,并且在 emit() 方法中也有效,因为它包含 postMessage() 方法。但是,尽管有这些有效条件,仍会引发错误。

下面是一个调试器视图:debugger view this.channel in the emit() method

我正在使用箭头函数,因此将尊重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" });

您能否提供任何见解,说明为什么会出现这种错误以及解决它的潜在方法?

javascript 这个 广播频道

评论

0赞 Titus 6/29/2023
您已使用。那不应该吗?setInterval(() => this.emit, intervalTime);setInterval(() => this.emit(), intervalTime);
0赞 ServerStorm 6/29/2023
stackoverflow.com/users/1552587/titus 是的,我已经在编译的 JS 中修复了它,但忘记在打字稿文件中修复它;但是,在添加 () 后,它仍然会抛出概述的错误。

答:

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 实例。

我希望这对其他人有所帮助