如果我向同一个webworker发送多条消息,它是否将它们排队并按顺序处理它们?

gor*_*dyr 7 javascript multithreading web-worker

正如标题所说......

基本上,如果我有一个webworker并一次发布1000条消息.

每条消息都会导致工作人员执行处理密集型操作.

在上一个完成后,我是否最好将每个消息顺序发布给webworker,或者我可以安全地将所有请求发送给工作人员,因为他们知道他们只会在完成后逐个处理并返回吗?

如果我这样做,我最好在工人中实施排队系统吗?还是没必要?

我知道这个单个工作者只是一个单独的线程,因此javascript操作确实会在webworker本身内同步发生,但我担心的是类似的争用,即一次执行200个ajax请求会使浏览器瘫痪.

我希望这样做.

aps*_*ers 6

工作人员将消息排队(具体来说,它会将调用排队onmessage)并在工作者的调用堆栈为空时处理每条消息.

但是,这意味着异步操作可能导致在任何特定操作完成之前处理输入多个消息.例如:

onmessage = function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/" + e.data);
    xhr.onload = function() {
        postMessage(xhr.responseText);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你一次传入1000条消息,我怀疑浏览器会在postMessage内部运行之前触发1000个Ajax请求(或至少很多请求)onload.这是因为onload在Ajax调用完成之前不会运行,并且每次onload调用都将被添加到事件队列中,这些调用onmessage是在Ajax fetch完成之前所请求的任何挂起调用之后.

如果你想确保一次只有一个Ajax请求,你确实可以实现一个只在onload被调用时才移动的内部队列:

var queue = [];
var busy = false;

onmessage = function(e) {
    if(busy) {
        queue.push(e);
    }
    else {
        busy = true;
        runAjax(e);
    }
}

var runAjax = function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", e.data);
    xhr.onload = function() {
        postMessage(xhr.responseText);
        if(queue.length) {
            // run the next queued item
            runAjax(queue.shift());
        } else {
            busy = false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,第一条消息进入else块,该块设置busy = true并运行Ajax提取.以下999消息被路由到该if块,因为busytrue(并且false在Ajax请求完成并且 queue为空之前不会成为).只有在Ajax请求完成后才会处理排队的消息.

如果你想在当时容忍超过一个Ajax请求,你可以使用一个计数器来代替布尔值:使用busy++busy--,而不是设置truefalse,并测试优秀的当前连接数没有达到您允许的上限(即,if(busy == 5)而不是if(busy)).