WebWorker 的执行范围与传统 JavaScript 的“窗口”上下文完全分离。脚本是否有标准方法来确定它本身是否作为 WebWorker 执行?
我能想到的第一个“黑客”是检测工作人员范围内是否存在“窗口”属性。如果不存在,这可能意味着我们正在作为 WebWorker 执行。
其他选项是检测标准“窗口”上下文中不存在的属性。对于 Chrome 14,此列表当前包括:
FileReaderSync
FileException
WorkerLocation
importScripts
openDatabaseSync
webkitRequestFileSystemSync
webkitResolveLocalFileSystemSyncURL
检测 WorkerLocation 似乎是一个可行的候选者,但这仍然感觉有点黑客。有没有更好的办法?
编辑:这里是我用来确定正在执行的WebWorker中现在位于“窗口”中的属性的JSFiddle。
规格说:
在此版本的规范中,DOM API(节点对象、文档对象等)对工作人员不可用。
这表明检查是否存在
document
是检查您是否属于工人的好方法。或者,您可以尝试检查是否存在 WorkerGlobalScope
?
虽然帖子有点旧,但添加了一些通用替代品 Asynchronous.js库(作者用于通用处理异步/并行进程的库)中使用的内容如下:
// other declarations here
,isNode = ("undefined" !== typeof global) && ('[object global]' === Object.prototype.toString.call(global))
// http://nodejs.org/docs/latest/api/all.html#all_cluster
,isNodeProcess = isNode && !!process.env.NODE_UNIQUE_ID
,isWebWorker = !isNode && ('undefined' !== typeof WorkerGlobalScope) && ("function" === typeof importScripts) && (navigator instanceof WorkerNavigator)
,isBrowser = !isNode && !isWebWorker && ("undefined" !== typeof navigator) && ("undefined" !== typeof document)
,isBrowserWindow = isBrowser && !!window.opener
,isAMD = "function" === typeof( define ) && define.amd
,supportsMultiThread = isNode || "function" === typeof Worker
,isThread = isNodeProcess || isWebWorker
// rest declarations here..
这对我有用
if (self.document) {
console.log('We are calculating Primes in Main Thread');
} else {
console.log('We are calculating Primes in Worker Thread');
}
这对我有用:
if (self instanceof Window) {
// not in worker
}
我知道这是一个旧方法,但我没有看到这个方法,但我更喜欢它。其他人也可能。
“navigator”在 Workers 和 Windows 中都存在,但类型名称分别为“WorkerNavigator”和“Navigator”。
const inWorker = navigator.constructor.name === 'WorkerNavigator';
我喜欢这种方法,因为库有时可以向工作全局范围添加假“文档”对象或其他对象,以使其他有问题的库正常工作。此方法避免使用可能创建的虚拟变量来欺骗脚本。
还有更多:
WorkerNavigator
等等
除非有关键字来检测网络工作者,否则您必须使用变量。 (没有什么可以阻止流氓脚本在您的脚本设置或替换变量之前运行。)
因此,假设您的脚本之前没有运行任何恶意脚本,则以下任何行都将起作用:
this.DedicatedWorkerGlobalScope?this.__proto__ === this.DedicatedWorkerGlobalScope.prototype:false
this.WorkerGlobalScope?this.__proto__.__proto__ === this.WorkerGlobalScope.prototype:false // works for shared workers too
this.constructor === this.DedicatedWorkerGlobalScope //or SharedWorkerGlobalScope
!(this.DedicatedWorkerGlobalScope === undefined)
!(this.DedicatedWorkerGlobalScope === undefined)
您也可以使用
self
§ 代替 this
,但由于 this
无法设置,所以更简洁。
我更喜欢:
this.DedicatedWorkerGlobalScope !== undefined
当然,如果你只有worker上下文和window上下文,你可以对window上下文进行逆向测试。例如
this.Window === undefined
。