同时运行两个 JS 网络工作者:一个被卡住了

simultaneous runs of two JS webworkers: one gets stuck

我正在开发一个封闭系统 Web 应用程序,以帮助公司处理日常在线商务事务。这意味着,一方面它不会对 public 开放,另一方面:它必须处理大量数据,同时保持流畅的工作体验。

这就是为什么我转向 JS 中的 Web Worker 以 运行 在后台进行各种数据库访问和数据加载。 我的理解是,不仅主要 UI/main JS 保持不间断,而且不同的网络工作者 运行 也不会相互阻碍。

我现在有以下设置:

mainJS:函数 statusCheck 哪个 运行s 在页面加载:

function statusCheck() {
    if(typeof(w__statusCheck) == "undefined") {
        var w__statusCheck = new Worker("...statusCheck.js");
        w__statusCheck.postMessage("go");
        w__statusCheck.onmessage = function(e) {
            var message = JSON.parse(e.data);
            if(message.text!=undefined) displayMessage(message.text);
        }
}

statusCheck.js 工人就是这样:

function checkStatus() {
        console.log("statusCheck started");
        // I will leave standard parts out:
            // creating and testing the ajax variable against different browsers

        ajaxRequest.onreadystatechange = function() {
            if(ajaxRequest.readyState == 4) {
                self.postMessage(ajaxRequest.responseText);

                var timer;
                timer = self.setTimeout(function(){
                    checkStatus();
                }, 1000);
            }
        }

        ajaxRequest.open("GET", "...worker_statusCheck.php", true);
        ajaxRequest.send(null);
    }

    this.onmessage = function(e){
        checkStatus();
    };

如您所见,它每秒(目前)重新启动一次。生产中的时间间隔可能会更长。 worker_statusCheck.php 简单地从数据库中获取不同的东西并将它们编织成一个 JSON 对象,它给我系统状态。

效果很好。

现在我有另一个工作人员,它应该通过单击 link 来启动,以有效地调用一些 php 来执行操作: mainJS loadWorker

function loadWorker(url="") {
    console.log("loadWorker started");

    if(url!="") {
        var uniqueID = "XXX" // creating a random ID based on timestamp and Math.random()

    if(typeof(window[uniqueID]) == "undefined") {
        var variables = { ajaxURL: url };
        window[uniqueID] = new Worker("....loadWorker.js");
        window[uniqueID].postMessage(JSON.stringify(variables));
        window[uniqueID].onmessage = function(e) {
            var message = JSON.parse(e.data);
            if(message["success"]!=undefined) {
                variables["close"] = "yes";
                window[uniqueID].postMessage(JSON.stringify(variables));
            }
        }
}

每次点击某个 link 都会调用它,创建一个唯一命名的工作人员,运行s 它,接收数据并告诉工作人员 close()

php 再次执行它的操作,并在冗长过程的每一步之后在数据库中写入进度更新。这些进度更新是我使用上述重复 statusCheck 从数据库中获取的。

现在,我可以在数据库中看到带有时间戳的条目,所以我知道它们是按时间写入的。 因此,两个工人都可靠地完成了他们的工作 运行。但我注意到,每当我启动手动(随机命名)工作人员时,statusCheck 实际上会停止执行。它只是卡住了......我能够通过两个工作人员的控制台输出来确认这一点。所以看起来卡住的不是主要的 JS,而是 statusCheck 实际上暂停了......并在 loadWorker 完成后恢复。

我是不是漏掉了一些基本的东西?任何见解将不胜感激,因为我是网络工作者这个概念的新手。

谢谢 :)

您的问题缺乏资源来真正找出问题所在。我同意 two web workers can operate at the same time,即使是同步操作。我针对 for 循环和同步 XHR 请求对此进行了测试。

虽然我会推荐很多东西。

首先 - 除非您使用一些 CPU 繁重的算法处理数据,否则网络工作者是在浪费时间。 XHR 请求不会阻塞主线程(除非你明确要求他们这样做)。

  1. statusCheck()中声明了var w__statusCheck,这意味着局部变量。因此,从外部范围来看,它始终为 null。一旦工作程序中没有代码 运行,它可能会被垃圾收集。
  2. 不要使用XMLHttpRequest.onreadystatechange。使用 onloadonerror.
  3. 变量的随机唯一 ID 几乎总是错误的。如果您完全需要存储工作人员引用,请给它一个合理的名称(例如,它应该加载的 url)或使用增量 ID。
  4. 不要 stringify 将您post 的数据发送给网络工作者。它已经由浏览器为您完成,可能以更优化的方式完成。将数据转换成某种东西是人们对网络工作者所做的最常见的愚蠢事情。

此外,当 post 提出问题时,至少要确保代码有意义。在你的 post curly 大括号不匹配。

好吧..我明白了: 我一直在找错地方。事实证明,我已经在工作人员调用的所有 php 脚本中初始化了我的 php 会话。我的两个平行工人都叫一个。所以会话文件被第一个 php 脚本锁定,第二个必须等到它再次打开。不是工人或 JS 受到阻碍,而是 php.

我现在从我的 statusCheck.php 中取出了会话初始化,它非常有效。我将把它保留在那些处理用户输入响应的其他人中,因为它实际上是有意义的:用户点击按钮 "compile data XY",这是工作人员 运行 并需要一段时间。尽管他很不耐烦,但他已经点击了下一步按钮 "show this data"... 并且由于锁定的会话文件,我对这些操作有一个整齐的队列。 :)

我仍然会牢记以上建议并努力改进我的代码。 :)