22

我无法在 HTML5 web worker中访问 jQuery 。有没有办法我可以做到这一点?

4

7 回答 7

26

tl;dr:在 jQuery 之前包含这个脚本

JQuery 最初会访问许多document属性来检查浏览器功能。document未在 Worker 中定义,此时您实际上无法Document在 Web Worker 中创建实例。JQuery 并没有为此做好准备 - 正如您在对您的问题的评论中看到的那样,似乎没有人理解您将如何使用没有 DOM 的 JQuery。

正如我所说,因为 JQuery 需要document初始化,所以我创建了一个虚拟的假文档对象。此对象在 JQuery 测试期间充当真实文档:

var document = self.document = {parentNode: null, nodeType: 9, toString: function() {return "FakeDocument"}};
var window = self.window = self;
var fakeElement = Object.create(document);
fakeElement.nodeType = 1;
fakeElement.toString=function() {return "FakeElement"};
fakeElement.parentNode = fakeElement.firstChild = fakeElement.lastChild = fakeElement;
fakeElement.ownerDocument = document;

document.head = document.body = fakeElement;
document.ownerDocument = document.documentElement = document;
document.getElementById = document.createElement = function() {return fakeElement;};
document.createDocumentFragment = function() {return this;};
document.getElementsByTagName = document.getElementsByClassName = function() {return [fakeElement];};
document.getAttribute = document.setAttribute = document.removeChild = 
  document.addEventListener = document.removeEventListener = 
  function() {return null;};
document.cloneNode = document.appendChild = function() {return this;};
document.appendChild = function(child) {return child;};

请注意,这个假文档只是为了允许 jQuery 加载,它不会允许任何真正的 DOM 操作。

示例用法:

importScripts("workerFakeDOM.js");
importScripts('jquery-2.1.4.min.js');
console.log("JQuery version:", $.fn.jquery);

测试脚本

允许您使用我的脚本尝试各种版本的 JQuery。

JSfiddle

检查您是否正在使用http://,我的域不适用于https://

下载为脚本

于 2015-11-26T18:09:00.437 回答
13

Tomáš Zato 的答案是正确的,但不再适用于较新的 jQuery 版本。我为 jQuery 3.1.1 添加了更多内容:

var document = self.document = { parentNode: null, nodeType: 9, toString: function () { return "FakeDocument" } };
var window = self.window = self;
var fakeElement = Object.create(document);
fakeElement.nodeType = 1;
fakeElement.toString = function () { return "FakeElement" };
fakeElement.parentNode = fakeElement.firstChild = fakeElement.lastChild = fakeElement;
fakeElement.ownerDocument = document;

document.head = document.body = fakeElement;
document.ownerDocument = document.documentElement = document;
document.getElementById = document.createElement = function () { return fakeElement; };
document.createDocumentFragment = function () { return this; };
document.getElementsByTagName = document.getElementsByClassName = function () { return [fakeElement]; };
document.getAttribute = document.setAttribute = document.removeChild =
    document.addEventListener = document.removeEventListener =
    function () { return null; };
document.cloneNode = document.appendChild = function () { return this; };
document.appendChild = function (child) { return child; };
document.childNodes = [];
document.implementation = {
    createHTMLDocument: function () { return document; }
}
于 2017-04-03T07:19:29.407 回答
4

有没有人尝试过 jQuery - No DOM Edition?https://github.com/kpozin/jquery-nodom

这是 jQuery 库的一小部分,旨在用于 Web Worker 上下文,其中大多数浏览器 API 都不存在。

这主要是通过修改 jQuery 构建指令(Makefile)以仅包含非 DOM 模块来实现的。

这可能有助于解决问题,因为此构建没有 DOM 依赖项,这是在 webworker 中导入 jQuery 时的一个障碍。将尽快为此提供一些示例代码

于 2016-04-06T11:44:37.203 回答
1

jQuery 自己的一位领导者提供了一个很好的插件,可以将 Web Worker 与 jQuery 一起使用。在 GitHub 上查看他的插件。

于 2012-05-08T02:00:24.890 回答
0

是否使用:

importScripts("jQueryWhatever.js");
$.blahblahblah();

没有按预期工作?我怀疑它会毫无问题地加载 jQuery,但大多数与 good-ole $ 相关的调用将无法按预期工作,因为 WebWorker 内部没有 DOM 访问。

于 2014-05-25T20:45:09.903 回答
0

作为替代方案,您可以使用Cheerio

专为服务器设计的核心 jQuery 的快速、灵活和精简的实现。

您只需要浏览模块,并将生成的文件加载到您的网络工作者中。然后,您将能够解析您的字符串文档并像 jQuery 一样查询它:

$ = cheerio.load('<h2 class="title">Hello world</h2>')
于 2016-06-23T15:30:52.217 回答
0

jQuery 3.3.1

我使用了Luke Vo的代码,不得不添加一些额外的代码。我将此功能放在我的网络工作者中并且效果很好:

    const webWorkerJQueryFix = () => {
    document = self.document = { parentNode: null, nodeType: 9, toString: () => { return "FakeDocument" } };
    window = self.window = self;
    const fakeElement = Object.create(document);
    fakeElement.nodeType = 1;
    fakeElement.toString = () => { return "FakeElement" };
    fakeElement.parentNode = fakeElement.firstChild = fakeElement.lastChild = fakeElement;
    fakeElement.ownerDocument = document;

    document.innerHTML = "";
    document.head =
        document.body =
        fakeElement;
    document.ownerDocument =
        document.documentElement =
        document;

    document.createElement =
        document.getElementById =
        document.getElementsByClassName =
        document.getElementsByTagName = () => { return [fakeElement]; };

    document.appendChild = (child) => { return child; };

    document.createDocumentFragment = () => {
        this.appendChild = document.appendChild;
        return this;
    };

    document.getAttribute =
        document.removeChild =
        document.addEventListener =
        document.removeEventListener =
        document.setAttribute = () => { return null; };

    document.cloneNode = () => {
        this.cloneNode = document.cloneNode;
        this.lastChild = {
            checked: false,
        }
        return this;
    };

    document.childNodes = [];
    document.implementation = {
        createHTMLDocument: () => { return document; }
    }
}
于 2021-09-15T19:18:57.717 回答