是否可以终止正在运行的Web工作者?

时间:2014-02-07 10:35:19

标签: javascript web-worker

我有一个Web工作人员使用ajax-requests运行耗时的例行任务。我可以从主线程中终止它们而不是等待它们完成吗?

这就是我如何产生并终止它:

$("button.parse-categories").click(function() {
    if (parseCategoriesActive==false) {
        parseCategoriesActive = true;
        parseCategoriesWorker = new Worker("parseCategories.js");


        $("button.parse-categories-cancel").click(function() {
            parseCategoriesWorker.terminate();
            parseCategoriesActive = false;
        });             
    }
});

这是工人代码:

function myAjax(url, async, callback) {
    xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange=function() {
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
            callback(xmlhttp.responseText);
        if (xmlhttp.readyState==4 && xmlhttp.status!=200) {
            self.postMessage("error");
            throw "error in ajax: "+xmlhttp.status;
        }
    }
    xmlhttp.open("GET", url, async);
    xmlhttp.send();
}

var parseCategoriesActive = true;
var counter = 0;
do {
    myAjax('parser.php', false, function(resp) {
        if (resp=='success')
            parseCategoriesActive = false;
        else {
            counter += Number(resp);
            self.postMessage(counter);
        }       
    });
} while (parseCategoriesActive==true);

3 个答案:

答案 0 :(得分:7)

您可以使用terminate()杀死任何网络工作者。

引自MDN

  

Worker.terminate()方法立即终止Worker。这并不能为工人提供完成业务的机会;它只是立即停止。

答案 1 :(得分:2)

我做了这个简单的脚本,看起来FF和Chrome的问题仍然存在:

    var myWorker = new Worker("w.js");

    myWorker.onmessage = function(e) {
        console.log('Message received from worker:'+e.data);
    }
    myWorker.postMessage(100);
    setTimeout(stopWW, 500) ;

    function stopWW(){
        console.log('TERMINATE');
        myWorker.terminate();
    }

而网络工作者是:

    onmessage = function(e) {
      var n = e.data;
      console.log('Message received from main script:'+n);
      for (var i=0;i<n;i++){
        console.log('i='+i);
         postMessage(i);
      } 
    }

主线程终止webworker后不再接收postmessage但是webworker仍然在场景下运行,这是一个输出:

"Message received from main script:100" w.js:3:2
"i=0" w.js:5:1
"Message received from worker:0" w.html:6:2
"i=1" w.js:5:1
...
"Message received from worker:21" w.html:6:2
"i=22" w.js:5:1
"TERMINATE" w.html:13:1
"i=23" w.js:5:1
"i=24" w.js:5:1
...
"i=99" w.js:5:1

答案 2 :(得分:0)

OP明确要求:

  

我可以从主线程终止它们而不是等待它们   完成?

他并没有问工人应该如何优雅地退出内部。他想非常不合理地从外部线程中杀死任何工作者。

  • 假设工作者实例位于上下文范围内,您可以通过调用其terminate()函数来终止任何 Web工作者。

网络工作者也有生命周期。他们将在特定条件下自行终止。

  • 您可以通过关闭创建它的页面/框架来终止专用工作程序。 这就是专用的意思 - 它只允许服务一个 页。关闭页面会调用专用工作者 自终止序列。

  • 您可以通过关闭域的所有页面来终止共享工作程序 创造了它。这就是共享的含义 - 它是 允许从域中提供多个页面。关闭所有域名页面 调用共享工作者的自终止序列。

  • 也可以通过关闭所有域名来杀死其他工作者类型。

这是一个终止一些不受欢迎的工作机器人窃取CPU的例子:

// Create worker bots that consume CPU threads

var Blob = window.Blob;
var URL  = window.webkitURL || window.URL;


var numbots = 4;
var bots    = []; 
var bot     = "while(true){}"; 

bot = new Blob([bot], { type: 'text/javascript' });
bot = URL.createObjectURL(bot);

// Intruders ...
for (var i=0; i<numbots; i++)
     bots[i] = new Worker(bot); 

document.getElementById("alert").play(); 

// Hasta la vista ...
function terminator(){
    if (bots){
        for (worker in bots)
            bots[worker].terminate();

        document.getElementById("terminator").play();
        bots = null;
    }
}
  
<img src="https://i.imgur.com/BHsjSzj.jpg" width="100%" onclick="terminator()">
<audio id="terminator" src="http://dcerisano.github.io/assets/audio/hastalavista.mp3">
<audio id="alert" src="http://dcerisano.github.io/assets/audio/alert.mp3">

  • 使用CPU监视器确认代码段正在运行。
  • 按按钮终止工作机器人。
  • “隐藏结果”会关闭代码段页/框,也会终止 工人机器人。

希望这个答案对那些希望构建应用程序的人有用,这些应用程序可以搜寻和杀死作为网络工作者实施的不受欢迎的机器人(例如, bitmining bot ,窃取你的电力,带宽,并使你成为一个附件庞)

例如,this Chrome extension检测并有选择地阻止网络工作者(各种机器人,包括矿工)。