Скрещиваем WebWorker и Promise
Если уж есть необходимость скрещивать WebWorker с XMLHttpRequest, то пора бы скрестить его с любой функцией, а заодно разобраться с обещаниями ES6.Цель — научиться делать вот так: new PromiseWorker (array => array.sort ()).Invoke ([3,2,1]).then (result => console.log (result));(Здесь и далее используются arrow functions для краткости)
Как известно, true-way для создания воркера — передать путь к файлу в качестве единственного параметра: new Worker (»/JS/worker.js») . повесить обработчик onmessage, вызывать postmessage и придерживаться подобного стиля в файле воркера. По моему мнению на одну функцию слишком жирно создавать целый файл, да и возиться с событиями-обработчиками уже не комильфо. Хорошо, что есть Blob и уже упомянутые Promises.
Сначала надо сделать преобразование входной функции в приемлемый для воркера вид:
var FnToWorker = fn => { var workerBody = «self.addEventListener ('message',» + «function (d) {» + «var result;» + «try {» + «result = (» + fn.toString () + »)(d.data.Data);» + «self.postMessage ({ Result: result, Id: d.data.Id });» + »} catch (e) {» + «self.postMessage ({ Error: e, Id: d.data.Id });» + »}» + »});» var worker = new Worker (URL.createObjectURL (new Blob ([workerBody]))); return worker; } Да, тут отвратительная конкатенация строк, fn.toString () и прочие ужасные вещи… главное что этот код можно один раз написать и забыть о нем.Вот так будет выглядеть Invoke:
var promises = []; //Очередь вызовов var Invoke = data => { var message = { Data: data, Id: performance.now () }; //У каждого сообщения Id, чтобы ничего не путалось var p = new Promise ((resolve, reject) => { promises[message.Id] = { resolve: resolve, reject: reject }; }); worker.postMessage (message); //Запускаем воркер return p; } Использовать Promise не сложно: в конструктор передаем функцию от двух аргументов: resolve и reject. Это функции которые надо будет вызвать в случае успеха операции и неуспеха соответственно. В нашем случае они будут вызываться после того, как отработает воркер: var OnMessage = data => { if (data.data.Error) { promises[data.data.Id].reject (data.data.Result); } else { promises[data.data.Id].resolve (data.data.Result); } promises[data.data.Id] = undefined; } Ну и вот так оно будет выглядеть в сборе: http://jsfiddle.net/sXJ4M/1/
Конечно, сложно себе представить, где можно использовать воркеры в интернет-магазине, но в достаточно больших и сложных приложениях они очень помогают.
