【问题标题】:javascript passing a function object to a web worker - ERROR DataCloneError could not be clonedjavascript 将函数对象传递给网络工作者 - 错误 DataCloneError 无法克隆
【发布时间】:2019-10-29 16:08:08
【问题描述】:

我需要使用网络工作者打开一个单独的线程并执行一些繁重的 CPU 任务。

我需要给网络工作者一个函数调用和参数,然后得到返回,所以我选择了:

funcs.js

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

ma​​in.js

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

然后运行时错误:

DataCloneError:无法在Worker上执行postMessagefunction add(args) { return args[0] + args[1]; } 无法克隆。

似乎worker.postMessage 方法只允许传递字符串, 知道如何简单优雅地解决这个问题吗?

【问题讨论】:

    标签: javascript web-worker


    【解决方案1】:

    关于postMessage

    postMessage documentation 明确定义可以发送或不能发送给工作人员的内容:

    postMessage 只接受由结构化克隆算法处理的值或 JavaScript 对象,包括循环引用。

    看着the structured clone algorithm,它接受:

    所有原始类型(但不是符号)Boolean 对象、String 对象、日期RegExp (不保留lastIndex字段。)Blob文件FileListArrayBufferArrayBufferView (这基本上意味着所有类型的数组,如 Int32Array 等)ImageBitmap ImageDataArrayObject (这仅包括普通对象(例如来自对象字面量))地图设置

    但不幸的是:

    ErrorFunction对象不能被结构化克隆算法复制;尝试这样做会引发 DATA_CLONE_ERR 异常。

    所以功能绝对不是一种选择。一个简单的解决方案是直接在您的worker.js 文件中导入add,并将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;
            ....
    
    

    【讨论】:

    • 是的,这会起作用,但我仍然希望工作人员执行 func() 通用,在这里我需要提前了解我将使用的功能,做一个丑陋的开关/案例,这不像优雅我认为它可能是,但无论如何感谢这是第一步:-)
    • 不,即使你不能传递函数,你仍然可以传递比字符串更多的数据类型:可以克隆普通对象,(通常甚至是循环对象,即使 Chrome 的实现可能会失败在某些情况下),可以传递 Blob,可以传递 ArrayBuffers、ImageBitmap MessagePorts 等。
    • 非常感谢 Kaiido ?,今天学到了一些新东西并相应地更正了我的答案。
    • 非常感谢@sebastienbarbier(和@kaiido)在如何...做什么方面变得更加清晰和准确...似乎它只是可克隆的对象,这确实是让它工作的关键或抛出错误,如果有人知道替代方案...
    • 不客气@uzer44713543。如果您认为这是对其他人的有效答案,请随时mark the answer as accepted。 “接受答案很重要,因为它会奖励正确回答您问题的发布者,通知其他人您的问题已解决,并将答案置顶,以便阅读您问题的其他人首先阅读该答案。”
    猜你喜欢
    • 2017-11-07
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 2019-08-29
    • 2019-04-30
    相关资源
    最近更新 更多