JavaScript, передающий объект функции веб-работнику - ERROR DataCloneError не может быть клонирован - PullRequest
0 голосов
/ 29 октября 2019

Мне нужно использовать веб-работника, чтобы открыть отдельный поток и выполнить какую-то тяжелую задачу ЦП.

Мне нужно было бы поручить веб-работнику вызов функции и аргументы, а затем получить возврат, поэтому япошел за:

funcs.js

export default function add(args) {
  return args[0] + args[1];
}

main.js

import add from './funcs.js';
// [...]
this.worker.postMessage({func: add, args: [7, 3]});

затем ошибка времени выполнения:

DataCloneError: не удалось выполнить postMessage на Worker: function add(args) { return args[0] + args[1]; } не удалось клонировать.

Кажется, что метод worker.postMessage допускает только строкучтобы быть переданным, есть идеи, как я могу обойти это просто и элегантно?

1 Ответ

0 голосов
/ 29 октября 2019

О postMessage

Документация postMessage дает четкое определение того, что может или не может быть отправлено работнику:

postMessage принимает только значение или объект JavaScriptобрабатывается алгоритмом структурированного клона, который включает циклические ссылки.

Глядя на алгоритм структурированного клона , он принимает:

Всетип примитива s (но не символы) , логический объект, строка объект, дата , RegExp (поле lastIndex не сохраняется.) , Blob , Файл , FileList , ArrayBuffer , ArrayBufferView (Это в основном означает все типизированные массивы, такие как Int32Array и т. Д.) , ImageBitmap , ImageData , Array , Объект (Это включает в себя простые объекты (например, из литералов объектов)) , Карта , Набор

Но, к сожалению:

Ошибка и Функция объекты не могут дублироваться алгоритмом структурированного клонирования;попытка сделать это вызовет исключение DATA_CLONE_ERR.

Так что функция определенно не вариант. Простым решением было бы импортировать add непосредственно в ваш файл worker.js и заменить func на строку.

Javascript

this.worker.postMessage( {func: 'ADD', args:[7, 3]} );

worker.js

import add from './funcs.js';

onmessage = function(event) {
    const action = event.data;
    switch (action.func) {
        case 'ADD': {
            postMessage({
                result: add(action.args)
            });
        }
        break;
        ....

...