【问题标题】:Reliably detect if the script is executing in a web worker [duplicate]可靠地检测脚本是否在网络工作者中执行[重复]
【发布时间】:2014-05-13 06:07:16
【问题描述】:

我目前正在用 JavaScript 编写一个小库,以帮助我将一些繁重的计算委托给网络工作者。

出于某些原因(主要是为了能够在 UI 线程中进行调试,然后在工作线程中运行相同的代码),我想检测脚本当前是在工作线程中运行还是在 UI 线程中运行。

我不是经验丰富的 JavaScript 开发人员,我想确保以下函数能够可靠地检测我是否在工作人员中:

function testenv() {
    try{
        if (importScripts) {
            postMessage("I think I'm in a worker actually.");
        }
    } catch (e) {
        if (e instanceof ReferenceError) {
            console.log("I'm the UI thread.");
        } else {
            throw e;
        }
    }
}

那么,是吗?

【问题讨论】:

    标签: javascript web-worker


    【解决方案1】:

    这个游戏已经很晚了,但这是我能想到的最好、最防弹的方法:

    // run this in global scope of window or worker. since window.self = window, we're ok
    if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
        // huzzah! a worker!
    } else {
        // I'm a window... sad trombone.
    }
    

    【讨论】:

    • 是否:if (self.WorkerGlobalScope) {} else {} 也可以?只要没有人将 WorkerGlobalScope 添加到项目中...似乎有效且简洁。
    • 是的,你可以,但我进行了仔细检查,因为它比希望有人不会写 self.WorkerGlobalScope 更可靠(这通常不太可能,但我更喜欢默认为更防弹)
    • 这个答案比公认的答案要准确得多,但“我是一个窗口”只有在存在窗口时才是正确的。对于像 d8 这样的 shell,情况并非如此。
    • 是的,但这是一个注释 - 所以else 的情况可能是"I'm a meat popsicle"。它真正的意思是"I'm not a worker"
    • @Pacerier 你只是喜欢迂腐吗?当然,没有防弹之类的东西。我说的是防弹的。例如,您无法获得防弹,但这已尽可能接近。如果您不打算在对话中增加一些有价值的东西,那就把它带到别处。
    【解决方案2】:

    Emscripten 会:

    // *** Environment setup code ***
    var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
    var ENVIRONMENT_IS_WEB = typeof window === 'object';
    var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
    var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
    

    (Emscripten on Github)

    【讨论】:

    • 您可能还想查看@NikosM 的this answer 以了解Asynchronous.js 的作用。
    【解决方案3】:

    如前所述,another thread 中有一个答案,它说要检查窗口上是否存在文档对象。但是,我想对您的代码进行修改,以避免执行 slows execution of JS in Chrome 以及可能在其他浏览器中的 try/catch 块。

    编辑:我之前在假设全局范围内有一个窗口对象时犯了一个错误。我一般加

    //This is likely SharedWorkerContext or DedicatedWorkerContext
    window=this;
    

    在我的工作加载程序脚本的顶部,这允许所有使用窗口特征检测的函数不会崩溃。那么你就可以使用下面的函数了。

    function testEnv() {
      if (window.document === undefined) {
        postMessage("I'm fairly confident I'm a webworker");
      } else {
        console.log("I'm fairly confident I'm in the renderer thread");
      }
    }
    

    或者,只要它在顶级范围内,就没有窗口分配。

    var self = this;
    function() {
      if(self.document === undefined) {
        postMessage("I'm fairly confident I'm a webworker");
      } else {
        console.log("I'm fairly confident I'm in the renderer thread");
      }
    }
    

    【讨论】:

    • 感谢您指出应该避免使用 try/catch 的事实。因为它是用于我编写的玩具游戏引擎,所以速度对我来说是一个重要的方面。
    • 请注意,“self”实际上在 web workers developer.mozilla.org/en/docs/Web/Guide/Performance/…987654323@ 中默认可用
    • @JamiePate, this 也可以。见stackoverflow.com/a/45657328/632951
    • " 但是我想对您的代码进行修改以避免执行 try/catch 块,这会减慢 Chrome 中 JS 的执行速度" 我听说过更改某些代码的最糟糕的原因。恕我直言,但这是过早优化的定义。 try..catch 没有没有错误。此外,没有理由缓存循环变量,还有一百多种过早的优化模式是你不应该陷入的。使用尝试捕获。它不会影响你的表现。
    • 如果它位于代码的顶部(在定义任何变量之前),您只需测试typeof window == 'undefined'。这将是 UI 线程中的 true 和工作线程中的 false。似乎可以肯定的是,它将保持这种状态。
    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 2014-12-27
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 2012-08-13
    • 2012-08-21
    • 1970-01-01
    相关资源
    最近更新 更多