Converting circular structure to JSON
最近在项目中遇到了这个问题,头疼,弄了一下午才解决。做一个笔记吧。
1 Converting circular structure to JSON
- 我这个问题大致就是在使用pinia中出现了循环引用,意思是两个或多个模块、对象或依赖之间形成了相互依赖的链条。
- 在使用 Pinia 进行状态管理时,遇到 “Converting circular structure to JSON”
错误通常是因为你试图将一个包含循环引用的对象转换成 JSON。这个错误通常出现在你尝试 JSON.stringify()一个有循环引用的对象时,JavaScript 会抛出这个错误,因为 JSON.stringify() 无法处理循环结构。
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'kc'
| property 'subs' -> object with constructor 'Object'
--- property 'dep' closes the circle
at stringify (<anonymous>)
at y (index-DXHQc27t.js:30:51838)
at index-DXHQc27t.js:22:2683
at qa (index-DXHQc27t.js:14:38)
at kn (index-DXHQc27t.js:14:109)
at Wc.i.call (index-DXHQc27t.js:14:33736)
at b (index-DXHQc27t.js:10:15808)
at qa (index-DXHQc27t.js:14:46)
at om (index-DXHQc27t.js:14:1835)
2 方法
我们在使用vuex时,肯定需要持久化存储,我这个项目使用了pinia-plugin-persistedstate-2
插件,解决防止抛出循环引用
序列化和反序列化 序列化和反序列化允许您自定义持久化和重新水化的状态。
例如,如果您的状态有循环引用,您可能需要使用json-stringify-safe来防止抛出循环引用:
import { createPinia } from "pinia";
import { createPersistedStatePlugin } from "pinia-plugin-persistedstate-2";
import localforage from "localforage";
// https://pinia.vuejs.org/zh
export function useStore(app) {
// 初始化状态管理
const pinia = createPinia();
function safeStringify(obj) {
const seen = new WeakSet();
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return; // 发现循环引用时返回 undefined
}
seen.add(value);
}
return value;
});
}
// 启用持久化插件
pinia.use(
createPersistedStatePlugin({
// storage: localforage,
serialize: (value) => {
// 确保返回的是一个序列化的普通对象
return safeStringify(value);
},
deserialize: (value) => {
// 确保反序列化为普通对象
return JSON.parse(value);
},
})
);
// 注册状态管理
app.use(pinia);
}
用插件防止抛出循环引用问题,会有一些问题,所以直接写了一个方法来防止抛出循环引用。
一. 问题一
:RangeError: Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded 错误通常发生在 JavaScript 中,当函数出现递归问题或者无限循环时,调用栈超出了其最大限制。调用栈是用于管理函数调用的内存结构,当栈中的调用过多时,就会出现这个错误。
常见原因和解决方法:
- 无限递归
这是最常见的原因。递归函数如果没有正确的退出条件,可能会导致函数不断自我调用,从而使调用栈溢出。
function recursive() {
recursive(); // 没有退出条件,函数会一直自我调用
}
recursive();
解决方法:
确保递归函数有正确的退出条件(基准情况)。
function recursive(count) {
if (count > 10) return; // 基准情况,停止递归
recursive(count + 1);
}
recursive(0);
- 递归深度过深
即使递归使用得当,如果递归的深度过大,仍然可能导致栈溢出。
解决方法:
如果递归深度很大,考虑使用迭代的方式来替代递归。
function factorial(n) {
let result = 1;
for (let i = 1; i <= n; i++) {
result *= i;
}
return result;
}
console.log(factorial(1000)); // 对于大输入,使用迭代
- 循环引用
如果对象之间存在相互引用的关系(循环引用),那么像 JSON.stringify() 这样的操作就可能会在序列化时导致栈溢出错误。
let objA = {};
let objB = { objA };
objA.objB = objB;
JSON.stringify(objA); // 由于循环引用,会抛出 RangeError
解决方法:
处理循环引用时,可以使用像 flatted 这样的库,或者编写自定义的序列化方法来检测循环引用。
- 事件处理器或循环中的无限循环
在某些情况下,setInterval()、setTimeout() 或事件处理器中的无限循环可能导致栈溢出。
解决方法:
确保在循环或事件处理器中使用了合适的退出条件。
let count = 0;
setInterval(() => {
count++;
if (count > 1000) clearInterval(this); // 设置退出条件
}, 1000);
- 深度嵌套的对象
如果你正在处理深度嵌套的对象或数据结构(如大规模的树形结构或递归数据结构),可能会遇到栈溢出错误。
解决方法:
重新设计数据结构,或者将递归过程改为非递归方式,避免使用过深的递归。
问题二
DOMException: Failed to execute ‘setItem’ on ‘Storage’: Setting the value of ‘app’ exceeded the quota 通常发生在你尝试将过多数据存储到浏览器的 localStorage 或 sessionStorage
- localStorage 和 sessionStorage 都有大小限制,通常每个域名下的存储空间大约为
5MB。当你尝试存储超过这个大小的数据时,就会出现这个错误。
解决方法:
- 检查并减少数据大小
- 清理存储空间
原文地址:https://blog.csdn.net/qq_48763502/article/details/144427075
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!