Почему веб-рабочий не может вызвать функцию напрямую?

Мы можем использовать веб-исполнителя в HTML5 следующим образом:

var worker = new Worker('worker.js');

но почему мы не можем назвать такую ​​функцию?

var worker = new Worker(function(){
    //do something
});

Ответ 1

Это способ создания веб-работников. Они должны иметь свой собственный внешний JS файл и собственную среду, инициализированную этим файлом. Они не могут совместно использовать среду с вашим обычным глобальным пространством JS для многопоточных конфликтов.

Одна из причин, по которой веб-работникам не допускается прямой доступ к вашим глобальным переменным, заключается в том, что для синхронизации потоков между двумя средами это не то, что доступно (и это серьезно усложнит ситуацию). Когда веб-рабочие имеют свои собственные глобальные переменные, они не могут взаимодействовать с основным потоком JS, кроме как через очередь сообщений, которая правильно синхронизируется с основным потоком JS.

Возможно, когда-нибудь более продвинутые программисты JS смогут использовать традиционные технологии синхронизации потоков для совместного доступа к общим переменным, но пока связь между этими двумя потоками должна проходить через очередь сообщений, и веб-рабочий не может иметь доступ к основное окружение Javascript.

Ответ 2

Этот вопрос задан до, но по какой-то причине ОП решил удалить его.
Я отправляю свой ответ, если вам нужен способ создания веб-рабочего из функции.


В этом сообщении было показано три способа создания веб-рабочего из произвольной строки. В этом ответе я использую третий метод, так как он поддерживается во всех средах.

Необходим вспомогательный файл:

// Worker-helper.js
self.onmessage = function(e) {
    self.onmessage = null; // Clean-up
    eval(e.data);
};

В вашем фактическом Рабочем файле этот вспомогательный файл используется следующим образом:

// Create a Web Worker from a function, which fully runs in the scope of a new
//    Worker
function spawnWorker(func) {
    // Stringify the code. Example:  (function(){/*logic*/}).call(self);
    var code = '(' + func + ').call(self);';
    var worker = new Worker('Worker-helper.js');
    // Initialise worker
    worker.postMessage(code);
    return worker;
}

var worker = spawnWorker(function() {
    // This function runs in the context of a separate Worker
    self.onmessage = function(e) {
        // Example: Throw any messages back
        self.postMessage(e.data);
    };
    // etc..
});
worker.onmessage = function() {
    // logic ...
};
worker.postMessage('Example');

Обратите внимание, что области строго разделены. Переменные могут передаваться только с помощью worker.postMessage и worker.onmessage. Все сообщения структурированные клоны.

Ответ 3

Этот ответ может быть немного запоздалым, но я написал библиотеку, чтобы упростить использование веб-работников, и это может подойти OP. Проверьте это: https://github.com/derekchiang/simple-worker

Это позволяет вам сделать что-то вроде:

SimpleWorker.run({
  func: intensiveFunction,
  args: [123456],
  success: function(res) {
    // do whatever you want
  },
  error: function(err) {
    // do whatever you want
  }
})

Ответ 4

Хотя он не является оптимальным и упоминается в комментариях, внешний файл не нужен, если ваш браузер поддерживает blobURL для веб-работников. HTML5Rocks был вдохновение для моего кода:

function sample(e)
{
    postMessage(sample_dependency());
}

function sample_dependency()
{
    return "BlobURLs rock!";
}

var blob = new Blob(["onmessage = " + sample + "\n" + sample_dependency]);
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);

worker.onmessage = function(e)
{
    console.log(e.data);
};

worker.postMessage("");

Предостережения:

  • Работники blob не будут успешно использовать относительные URL-адреса. Ссылка HTML5Rocks охватывает это, но это не было частью исходного вопроса.

  • Люди сообщают о проблемах с использованием URL-адресов Blob с веб-рабочими. Я пробовал это с IE11 (независимо от того, что поставляется с FCU), MS Edge 41.16299 (Fall Creator Update), Firefox 57 и Chrome 62. Не имеет понятия о поддержке Safari. Те, которые я тестировал, работали.

  • Обратите внимание, что ссылки "sample" и "sample_dependency" в вызове конструктора Blob неявно вызывают Function.prototype.toString() как sample.toString() и sample_dependency.toString(), что сильно отличается от вызовов toString(sample) и toString(sample_dependency).

Отправлено это, потому что это первый stackoverflow, который возник при поиске веб-рабочих без запроса дополнительного файла.

Посмотрел на ответ Zevero, и код в его репо кажется похожим. Если вы предпочитаете чистую упаковку, это примерно то, что делает его код.

Наконец-то я здесь noob, поэтому любые/все исправления приветствуются.

Ответ 5

По дизайну веб-работники многопоточные, javascript однопоточно " *" несколько сценариев не могут работать одновременно.

ссылаются на: http://www.html5rocks.com/en/tutorials/workers/basics/

Ответ 6

Просто используйте мой крошечный плагин https://github.com/zevero/worker-create

и do

var worker_url = Worker.create(function(e){
  self.postMessage('Example post from Worker'); //your code here
});
var worker = new Worker(worker_url);