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

时间:2015-02-19 13:59:18

标签: javascript multithreading web-worker

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

基本上,如果我有一个网络工作者并一次发布1000条消息。

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

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

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

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

我希望这样做。

2 个答案:

答案 0 :(得分:6)

工作人员将对消息进行排队(具体而言,它会将调用排队到onmessage)并在工作者的调用堆栈为空时处理每条消息。

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

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

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

如果您想确保一次只有一个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;
        }
    }
}

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

如果您当时想要容忍多个Ajax请求,可以使用计数器而不是布尔值:使用busy++busy--而不是设置true和{{1并测试当前未完成的连接数未达到允许的最大值(即false而不是if(busy == 5))。

答案 1 :(得分:1)

Web Worker一次接收一条消息 - 任何排队都将由您自己的逻辑完成 - 为了最快速度将数据作为类型化数组传输,特别是一种名为Transferable Objects的形式 - 可能您可以放置​​许多(1000条)消息进入这样一个类型化的数组(float或int)并使它成为单个消息 - 从浏览器到Web Worker的实际数据传输,反之亦然 - 非常快速的类型为10兆字节的数组,以毫秒或更短的速度...与低级别类型的数组相比,此消息传递确实处理对象,但速度有所降低