【问题标题】:Why Web worker is creating a new Class Instance again on module import?为什么 Web 工作者在模块导入时再次创建一个新的类实例?
【发布时间】:2020-12-14 21:36:53
【问题描述】:

我们正在 web worker 上执行一个计时功能。我还有一个 Dispatcher 类,它为其他类创建单个实例以供使用,如下所示:

class Dispatcher {
constructor() {
        console.log("calling");
        this.events = {};
    }
//some code
}
const dispatcher = new Dispatcher();
export default dispatcher;

我已将此模块导入另一个名为 DataManager Class 的文件中:

import dispatcher from '../../utility/dispatcher';

export class DataManager {
  notifyRenderer = (data: ResultData): void => {
        dispatcher.dispatch(NOTIFY_EVENT, data);
  }
}

我的网络工作者正在创建这个类的一个新实例,从这里我们触发了一个用 DataManager 类编写的 notifyRenderer 方法。

import { DataManager } from "./data-manager";
let dm: DataManager;

addEventListener('message', (e) => {
    if (!dm) {
        dm = new DataManager();
    }

    const res = dm.addOrUpdateData(e.data.input, true);
    dm.notifyRenderer(res);
    postMessage({ type: 'Dispatch', res });
}, false);

我还附上了我的控制台屏幕截图,显示了 console.log("calling");两次。我不知道为什么 Dispatch 类构造函数会被调用两次。

我做错了什么吗?请在这方面需要帮助。

我觉得模块导入可能是问题所在。是吗?

从工人添加屏幕截图跟踪:

提前感谢您!

【问题讨论】:

  • 您的模块看起来不错。您是否正在实例化第二个工作人员?在页面本身(网络工作者之外)导入调度程序? “实时重新加载”与它有关吗?
  • 嗨@Bergi 感谢您的回复,是的,我正在实例化第二个工作人员,但它在完全不同的组件中。没有关系!。其次,我也在其他组件中导入调度程序。但是由于 mjs(require) 文件缓存机制,使得构造函数只被调用一次。但是在从工作线程调用函数到主线程时,构造函数会调用两次。我不知道为什么会这样!我将在描述中添加 console.trace() 屏幕截图。看看吧!
  • 主线程和每个工作线程都有自己的每个模块的实例。没有跨领域的模块缓存。您必须在您的应用程序中实例化一个调度程序,并从其他工作人员显式传递消息。
  • 哦,有没有文档。我可以在哪里阅读有关此限制的更多详细信息。其次,我该如何处理这个用例呢?任何的意见都将会有帮助!。因为我在主线程调度程序对象上注册的任何事件在工作线程中都不可用。

标签: javascript class events web-worker


【解决方案1】:

每个人都从那里学习错误和实践,我在这里也发生了同样的事情。

我的模块中的一切都是正确的,它是调度程序类、数据管理器类并实例化一个新的工作线程。问题是我在该模块的末尾创建了 Dispatcher Class 的单个实例,因为我认为结果导出将被缓存(根据 mjs(require) 文件缓存机制)并尝试在两个主线程中使用(导入)和工作线程,并且两个线程都在那里创建自己的模块实例版本。(我的错误!)

直到bergi 给了我一个提示,我才意识到。正确的方法是使用 postmessage 将数据从工作线程发送到主线程并在主线程上监听。

从工作线程发送:

postMessage(dm.addOrUpdateData(e.data.input, true) as ResultData);

在主线程上监听:

this.worker.onmessage = (e: MessageEvent) => {
            if (!e.data) return;
            dispatcher.dispatch(NOTIFY_EVENT, e.data);
        };

了解更多关于领域和帮助链接必须访问:

谢谢!

【讨论】:

    猜你喜欢
    • 2018-10-08
    • 2021-03-18
    • 2011-09-11
    • 2018-08-26
    • 2023-01-25
    • 2014-01-12
    • 2020-09-22
    • 1970-01-01
    • 2020-12-31
    相关资源
    最近更新 更多