错误的意思说明
“Failed to execute ‘postMessage’ on ‘Window’: # could not be cloned.” 这个错误表示你尝试在 Web Worker 中使用 postMessage 方法来发送一个对象,但是这个对象无法被序列化(即克隆)以传递给 Worker。
在 Web Workers 的上下文中, postMessage 方法用于在主线程和工作线程之间传递数据。由于 Web Workers 运行在不同的全局上下文中,所以传递给 postMessage 的数据必须能够被 结构化克隆算法 处理。这通常意味着你只能发送基本的数据类型(如字符串、数字、布尔值、null、undefined、ArrayBuffer、Blob、ImageBitmap、ImageData、File 和 FileList 等)或者可以序列化为这些类型的对象。
常见的不能发送的对象包括函数、DOM 节点、XMLHttpRequest 对象或者其它具有复杂内部状态的对象。如果你尝试发送这样的对象,你就会遇到 “could not be cloned” 的错误。
vue3使用报错场景
如下代码:创建ref 接收第三方包返回的对像,在点击按钮的时候,浏览器控制台就报错
<template>
<span @click="handleClick">按钮</span>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
// 假设引入第三方包
import thirdPackage from 'xxxxxx'
const testRef= ref({})
// 点击事件后只想第三方包的函数
const handleClick = ()=>{
(testRef.value as any).valid() // 这里就是报错的地方
}
onMounted(()=>{
// 初始化第三方包返回一个对像,使用ref 接收
thirdPackage.init().then((res:Record<string,any>)=>{
testRef.value = res
})
})
</script>
报错原因
虽然使用 ref.value 解包,但是返回的对像不是原始对像,而是一个代理响应式对象内部的真实值,这个代理对象具有额外的属性和方法,导致序列化错误。
在控制台打印数据对比可以明显的看到两者的区别 console.log(testRef.value,“–对比普通对像–”,{})
解决报错
使用 reactive 代替 ref ,在使用 toRaw 返回原始对像,代码如下:
<template>
<span @click="handleClick">按钮</span>
</template>
<script setup lang="ts">
import { reactive, toRaw, onMounted } from 'vue'
// 假设引入第三方包
import thirdPackage from 'xxxxxx'
const testRef= reactive({
thirdObj: {}
})
// 点击事件后只想第三方包的函数
const handleClick = ()=>{
(toRaw(testRef).thirdObj as any).valid()
}
onMounted(()=>{
// 初始化第三方包返回一个对像,使用ref 接收
thirdPackage.init().then((res:Record<string,any>)=>{
testRef.thirdObj= res
})
})
</script>