在 Web Worker 中注册事件监听器

The*_*ram 4 javascript web-worker

是否可以在 Web Worker 中注册除 和 之外的事件的侦听'message''error'?例如

addEventListener('keydown', function (e) {
  postMessage('test');
});
Run Code Online (Sandbox Code Playgroud)

编辑:

根据@TJCrowder 的说法,这是不可能的。然而,就我而言,我能够用消息来模拟它,就像这样:

在工人中:

const handlers = {};

function registerKeyHandler(keycode, callback) {
  postMessage({
    type: 'REGISTER_KEY_HANDLER',
    keycode: keycode,
  });

  handlers[keycode] = handlers[keycode] || [];
  handlers[keycode].push(callback);
}

function onKeydown(keycode) {
  const hs = handlers[keycode] || [];
  hs.forEach(h => h());
}

self.onmessage = function(msg) {
  switch (msg.type) {
    case 'KEYDOWN':
      onKeydown(msg.payload.keycode);
      break;
  }
};
Run Code Online (Sandbox Code Playgroud)

外部:

worker.onmessage = function(msg) {
  switch (msg.type) {
    case 'REGISTER_KEY_HANDLER':
      window.addEventListener('keydown', function (e) {
        if (e.keyCode !== msg.keycode) {
          return;
        }
        worker.postMessage({
          type: 'KEYDOWN',
          keycode: msg.keycode,
        });
      });
      break;
  }
};
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 5

不可以。Web 工作者无权访问 DOM,尤其是因为

  • 允许多个线程访问 DOM 会导致基于浏览器的代码面临全新(且非常棘手)的多线程错误类别;仅允许主 UI 线程更新 DOM 可以避免这种情况
  • 某些浏览器的 DOM 实现无法处理多线程访问

全局范围对象* 工人拥有的不是一个窗口,并且只具有网络工人规范中调用的最小功能,例如addEventListener(尽管奇怪的是仅在传递规范时提到),postMessageonmessageonerror属性等。

* (这是常见的,根据worker的类型有专用[for Worker]和共享[for SharedWorker]子接口)