Цель — научиться делать вот так: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://ift.tt/1sLepym
Конечно, сложно себе представить, где можно использовать воркеры в интернет-магазине, но в достаточно больших и сложных приложениях они очень помогают.
This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий