Возможно ли запустить Web Worker с кодом в памяти? [Дубликат]

Следующее описание взято из этой страницы :

Метод getElementsByClassName () возвращает коллекцию всех элементов в документе с указанным именем класса, так как объект NodeList.

Объект NodeList представляет собой набор узлов. К узлам можно обращаться по номерам индексов. Индекс начинается с 0.

Совет. Вы можете использовать свойство length объекта NodeList для определения количества элементов с указанным именем класса, затем вы можете прокручивать все элементы и извлекать нужную информацию .

blockquote>

Итак, поскольку параметр getElementsByClassName принимает имя класса.

Если это ваше тело HTML:





то var menuItems = document.getElementsByClassName('menuItem') вернет коллекцию (а не массив) из трех верхних

s, поскольку они соответствуют заданному имени класса.

Затем вы можете перебирать эти узлы (

s в этот случай) с помощью:

for (var menuItemIndex = 0 ; menuItems.length ; menuItemIndex ++) {
   var currentMenuItem = menuItems[menuItemIndex];
   // do stuff with currentMenuItem as a node.
}

Подробнее о различиях между элементами и узлами см. в этой записи .

70
задан Rob W 1 May 2012 в 09:05
поделиться

8 ответов

Резюме

  • blob: для Chrome 8+, Firefox 6+, Safari 6.0+, Opera 15 +
  • data:application/javascript для Opera 10.60 - 12
  • eval в противном случае (IE 10 +)

URL.createObjectURL(<Blob blob>) можно использовать для создания веб-рабочего из строки. Блаб может быть создан с использованием BlobBuilder API устарел или конструктор Blob .

Демонстрация: http: // jsfiddle .net / uqcFM / 49 /

// URL.createObjectURL
window.URL = window.URL || window.webkitURL;

// "Server response", used in all examples
var response = "self.onmessage=function(e){postMessage('Worker: '+e.data);}";

var blob;
try {
    blob = new Blob([response], {type: 'application/javascript'});
} catch (e) { // Backwards-compatibility
    window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
    blob = new BlobBuilder();
    blob.append(response);
    blob = blob.getBlob();
}
var worker = new Worker(URL.createObjectURL(blob));

// Test, used in all examples:
worker.onmessage = function(e) {
    alert('Response: ' + e.data);
};
worker.postMessage('Test');

Совместимость

Работники Web поддерживаются в следующих браузерах source :

  • Chrome 3
  • Firefox 3.5
  • IE 10
  • Opera 10.60
  • Safari 4

Поддержка этого метода основана на поддержке API Blob и метода URL.createObjectUrl. Blob Совместимость :

  • Chrome 8+ (WebKitBlobBuilder), конструктор 20+ (Blob)
  • Firefox 6+ ( MozBlobBuilder), конструктор 13+ (Blob)
  • Конструктор Safari 6+ (Blob)

IE10 поддерживает MSBlobBuilder и URL.createObjectURL. Тем не менее, попытка создания веб-рабочего из blob: -URL выдает SecurityError.

Opera 12 не поддерживает API URL. Некоторые пользователи могут иметь поддельную версию объекта URL, благодаря этому взлому в browser.js .

Падение 1: data-URI

Opera поддерживает URI-данные в качестве аргумента для конструктора Worker. Примечание. Не забудьте, чтобы выбрали специальные символы (такие как # и %).

// response as defined in the first example
var worker = new Worker('data:application/javascript,' +
                        encodeURIComponent(response) );
// ... Test as defined in the first example

Демо: http://jsfiddle.net / uqcFM / 37 /

Fallback 2: Eval

eval может использоваться как резерв для Safari (& lt; 6) и IE 10.

// Worker-helper.js
self.onmessage = function(e) {
    self.onmessage = null; // Clean-up
    eval(e.data);
};
// Usage:
var worker = new Worker('Worker-helper.js');
// `response` as defined in the first example
worker.postMessage(response);
// .. Test as defined in the first example
119
ответ дан Community 22 August 2018 в 20:40
поделиться
  • 1
    @BrianFreid Спасибо за ваше редактирование, но это не нужно. Если вы посмотрите несколько строк дальше, вы увидите, что «IE10 поддерживает MSBlobBuilder и URL.createObjectURL. Однако попытка создания веб-рабочего из blob: -URL выбрасывает SecurityError. & Quot ;. Таким образом, добавление MSBlobBuilder не будет иметь эффекта, единственным вариантом является резерв # 2. – Rob W 14 July 2012 в 08:55
  • 2
    Opera 12 больше не определяет URL (и, следовательно, не определяет никаких свойств на нем), а конструктор Blob в настоящее время достаточно хорошо поддерживается. – gsnedders 15 March 2013 в 15:11
  • 3
    Я подтвердил, что это все еще происходит в IE11, по крайней мере, в предварительном просмотре. – Benjamin Gruenbaum 28 June 2013 в 00:35
  • 4
    Поддерживаются ли dataURI только в Opera или во всех других браузерах (кроме IE)? – jayarjo 7 September 2014 в 20:17
  • 5
    @jayarjo data: -URIs для веб-работников также поддерживается в Firefox, но не в Chrome или Opera 15+. Производительность eval не актуальна, вы не собираетесь создавать миллионы веб-работников в секунду. – Rob W 7 September 2014 в 20:20

Расширяясь по коду @ Chanu_Sukarno, вы можете просто передать в рабочую функцию (или строку) эту функцию и выполнить ее внутри веб-работника:

async function doWorkerTask(workerFunction, input, buffers) {
  // Create worker
  let fnString = '(' + workerFunction.toString().replace('"use strict";', '') + ')();';
  let workerBlob = new Blob([fnString]);
  let workerBlobURL = window.URL.createObjectURL(workerBlob, { type: 'application/javascript; charset=utf-8' });
  let worker = new Worker(workerBlobURL);

  // Run worker
  return await new Promise(function(resolve, reject) {
    worker.onmessage = function(e) { resolve(e.data); };
    worker.postMessage(input, buffers);
  });
}

Вот пример того, как используйте его:

function myTask() {
  self.onmessage = function(e) {
    // do stuff with `e.data`, then:
    self.postMessage("my response");
    self.close();
  }
}
let output = await doWorkerTask(myTask, input, inputBuffers);
// now you can do something with `output` (which will be equal to "my response")


В nodejs doWorkerTask выглядит так:

async function doWorkerTask(workerFunction, input, buffers) {
  let Worker = require('webworker-threads').Worker;
  let worker = new Worker(workerFunction);

  // Run worker
  return await new Promise(function(resolve, reject) {
    worker.onmessage = function(e) { resolve(e.data); };
    worker.postMessage(input, buffers);
  });
}
1
ответ дан 2 revs 22 August 2018 в 20:40
поделиться

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

    <script type="javascript/worker">
        //WORKER FUNCTIONS
        self.onmessage = function(event) {
            postMessage('Hello, ' + event.data.name + '!');
        }
    </script>

    <script type="text/javascript">

        function inlineWorker(parts, params, callback) {

            var URL = (window.URL || window.webkitURL);

            if (!URL && window.Worker) {

                var worker = new window.Worker(URL.createObjectURL(new Blob([parts], { "type" : "text/javascript" })));

                worker.onmessage = function(event) {
                  callback(event.data);
                };

                worker.postMessage(params);

            } else {

                var postMessage = function(result) {
                  callback(result);
                };

                var self = {}; //'self' in scope of inlineWorker. 
                eval(parts); //Converts self.onmessage function string to function on self via nearest scope (previous line) - please email chrisgwgreen.site@gmail.com if this could be tidier.
                self.onmessage({ 
                    data: params 
                });
            }
        }

        inlineWorker(
            document.querySelector('[type="javascript/worker"]').textContent, 
            {
                name: 'Chaps!!'
            },
            function(result) {
                document.body.innerHTML = result;
            }
        );

    </script>
</body>

1
ответ дан Bojangles 22 August 2018 в 20:40
поделиться

В зависимости от вашего варианта использования вы можете использовать что-то вроде

task.js Упрощенный интерфейс для получения кода интенсивного процессора для работы на всех ядрах (node.js, и web)

Пример:

// turn blocking pure function into a worker task
const functionFromPostRequest = task.wrap('function (exampleArgument) {}');

// run task on a autoscaling worker pool
functionFromPostRequest('exampleArgumentValue').then(result => {
    // do something with result
});
1
ответ дан Chad Scira 22 August 2018 в 20:40
поделиться

Я согласен с текущим принятым ответом, но часто редактирование и управление рабочим кодом будет суете как его в виде строки.

Поэтому, возможно, мы сможем использовать подход ниже, где мы можем сохранить как функция, а затем скрыто для string-> blob:

// function to be your worker
function workerFunction() {
    var self = this;
    self.onmessage = function(e) {
        console.log('Received input: ', e.data); // message received from main thread
        self.postMessage("Response back to main thread");
    }
}


///////////////////////////////

var dataObj = '(' + workerFunction + ')();'; // here is the trick to convert the above fucntion to string
var blob = new Blob([dataObj.replace('"use strict";', '')]); // firefox adds "use strict"; to any function which might block worker execution so knock it off

var blobURL = (window.URL ? URL : webkitURL).createObjectURL(blob, {
    type: 'application/javascript; charset=utf-8'
});


var worker = new Worker(blobURL); // spawn new worker

worker.onmessage = function(e) {
    console.log('Worker said: ', e.data); // message received from worker
};
worker.postMessage("some input to worker"); // Send data to our worker.

Это проверено в IE11 + и FF и Chrome

5
ответ дан FrankerZ 22 August 2018 в 20:40
поделиться
  • 1
    @SenJacob Поскольку это не сообщество wiki-сообщения, вы должны подвергать потенциальные проблемы плакату через комментарий вместо редактирования. – FrankerZ 21 October 2016 в 11:49
  • 2
    @FrankerZ Извините. Я должен был заставить его работать в IE11 с изменениями, которые я сделал. @ ChanuSukarno Не могли бы вы проверить, есть ли изменения в версии 3 в порядке? – Sen Jacob 21 October 2016 в 12:22

Я сделал подход с большинством ваших идей и добавил некоторые из моих. Единственное, что нужно моему рабочему коду, это использовать «это» для обозначения области «я». Я уверен, что это очень полезно:

// Sample code
var code = function() {
    this.onmessage = function(e) {
        this.postMessage('Worker: '+e.data);
        this.postMessage('Worker2: '+e.data);
    };
};

// New thread worker code
FakeWorkerCode = function(code, worker) {
    code.call(this);
    this.worker = worker;
}
FakeWorkerCode.prototype.postMessage = function(e) {
    this.worker.onmessage({data: e});
}
// Main thread worker side
FakeWorker = function(code) {
    this.code = new FakeWorkerCode(code, this);
}
FakeWorker.prototype.postMessage = function(e) {
    this.code.onmessage({data: e});
}

// Utilities for generating workers
Utils = {
    stringifyFunction: function(func) {
        // Stringify the code
        return '(' + func + ').call(self);';
    },
    generateWorker: function(code) {
        // URL.createObjectURL
        windowURL = window.URL || window.webkitURL;   
        var blob, worker;
        var stringified = Utils.stringifyFunction(code);
        try {
            blob = new Blob([stringified], {type: 'application/javascript'});
        } catch (e) { // Backwards-compatibility
            window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
            blob = new BlobBuilder();
            blob.append(stringified);
            blob = blob.getBlob();
        }

        if ("Worker" in window) {
            worker = new Worker(windowURL.createObjectURL(blob));
        } else {
            worker = new FakeWorker(code);
        }
        return worker;
    }
};

// Generate worker
var worker = Utils.generateWorker(code);
// Test, used in all examples:
worker.onmessage = function(e) {
    alert('Response: ' + e.data);
};
function runWorker() {
    worker.postMessage('working fine');
}

Демо: http://jsfiddle.net/8N6aR/

3
ответ дан lukelalo 22 August 2018 в 20:40
поделиться

Вы можете получить реальные данные из объекта objectURL , а не просто blob, изменив responseType на "text" или "arraybuffer".

Вот назад из text/javascript в blob - objectURL обратно в blob или text/javascript.

, если вам интересно, я используя его для создания веб-рабочего без внешних файлов , вы можете использовать его для возврата двоичного содержимого, например видео на YouTube;) (из атрибута ресурса & lt; video & gt;)

var blob = new Blob(['self.onmessage=function(e){postMessage(e)}'],{type: 'text/javascript'});   //->console: (object)   Blob {size: 42, type: "text/javascript", slice: function}

var obju = URL.createObjectURL(js_blob); //->console:  "blob:http%3A//stackoverflow.com/02e79c2b-025a-4293-be0f-f121dd57ccf7"

var xhr = new XMLHttpRequest();
xhr.open('GET', 'blob:http%3A//stackoverflow.com/02e79c2b-025a-4293-be0f-f121dd57ccf7', true);
xhr.responseType = 'text'; /* or "blob" */
xhr.onreadystatechange = function(){
  if(xhr.DONE !== xhr.readyState) return;

  console.log(xhr.response);
}
xhr.send();

/*
  responseType "blob" ->console: (object)   Blob {size: 42, type: "text/javascript", slice: function}
  responseType "text" ->console: (text)     'self.onmessage=function(e){postMessage(e)}'
*/
0
ответ дан user 22 August 2018 в 20:40
поделиться

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

var worker_url = Worker.create("self.postMessage('Example post from Worker');");
var worker = new Worker(worker_url);

Но вы также можете дать ему функцию.

-1
ответ дан zevero 22 August 2018 в 20:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: