Chrome发送请求错误:TypeError:将循环结构转换为JSON
我有以下…
chrome.extension.sendRequest({ req: "getDocument", docu: pagedoc, name: 'name' }, function(response){ var efjs = response.reply; });
其中要求以下..
case "getBrowserForDocumentAttribute": alert("ZOMG HERE"); sendResponse({ reply: getBrowserForDocumentAttribute(request.docu,request.name) }); break;
但是,我的代码永远不会达到“ZOMG HERE”,而是在运行chrome.extension.sendRequest
引发以下错误
Uncaught TypeError: Converting circular structure to JSON chromeHidden.JSON.stringify chrome.Port.postMessage chrome.initExtension.chrome.extension.sendRequest suggestQuery
有谁知道是什么原因造成的?
这意味着你在请求中传递的对象(我猜它是pagedoc
)有一个循环引用,如:
var a = {}; ab = a;
JSON.stringify
不能转换这样的结构。
注意 :即使没有附加到DOM树,DOM节点也是如此,这些节点有循环引用。 每个节点都有一个ownerDocument
,在大多数情况下它引用document
。 document
至少通过document.body
和document.body.ownerDocument
引用DOM树,再次引用document
,这只是DOM树中多个循环引用之一。
根据Mozilla的JSON文档 , JSON.Stringify
有第二个参数JSON.Stringify
,可以用来在解析树时过滤/忽略子项。 但是,也许你可以避免循环引用。
在Node.js中,我们不能。 所以我们可以这样做:
function censor(censor) { var i = 0; return function(key, value) { if(i !== 0 && typeof(censor) === 'object' && typeof(value) == 'object' && censor == value) return '[Circular]'; if(i >= 29) // seems to be a harded maximum of 30 serialized objects? return '[Unknown]'; ++i; // so we know we aren't using the original object anymore return value; } } var b = {foo: {bar: null}}; b.foo.bar = b; console.log("Censoring: ", b); console.log("Result: ", JSON.stringify(b, censor(b)));
结果:
Censoring: { foo: { bar: [Circular] } } Result: {"foo":{"bar":"[Circular]"}}
不幸的是,似乎最多有30次迭代,然后自动假设它是循环的。 否则,这应该工作。 我甚至在这里使用了areEquivalent
,但是JSON.Stringify
仍然会在30次迭代之后抛出异常。 尽管如此,如果你真的需要的话,也可以在顶层获得一个像样的对象。 也许有人可以改善这个呢? 在一个HTTP请求对象的Node.js中,我得到:
{ "limit": null, "size": 0, "chunks": [], "writable": true, "readable": false, "_events": { "pipe": [null, null], "error": [null] }, "before": [null], "after": [], "response": { "output": [], "outputEncodings": [], "writable": true, "_last": false, "chunkedEncoding": false, "shouldKeepAlive": true, "useChunkedEncodingByDefault": true, "_hasBody": true, "_trailer": "", "finished": false, "socket": { "_handle": { "writeQueueSize": 0, "socket": "[Unknown]", "onread": "[Unknown]" }, "_pendingWriteReqs": "[Unknown]", "_flags": "[Unknown]", "_connectQueueSize": "[Unknown]", "destroyed": "[Unknown]", "bytesRead": "[Unknown]", "bytesWritten": "[Unknown]", "allowHalfOpen": "[Unknown]", "writable": "[Unknown]", "readable": "[Unknown]", "server": "[Unknown]", "ondrain": "[Unknown]", "_idleTimeout": "[Unknown]", "_idleNext": "[Unknown]", "_idlePrev": "[Unknown]", "_idleStart": "[Unknown]", "_events": "[Unknown]", "ondata": "[Unknown]", "onend": "[Unknown]", "_httpMessage": "[Unknown]" }, "connection": "[Unknown]", "_events": "[Unknown]", "_headers": "[Unknown]", "_headerNames": "[Unknown]", "_pipeCount": "[Unknown]" }, "headers": "[Unknown]", "target": "[Unknown]", "_pipeCount": "[Unknown]", "method": "[Unknown]", "url": "[Unknown]", "query": "[Unknown]", "ended": "[Unknown]" }
我创建了一个小的Node.js模块在这里执行此操作: https : //github.com/ericmuyser/stringy随意改善/贡献!
一种方法是从主要对象中去除对象和功能。 并串化更简单的形式
function simpleStringify (object){ var simpleObject = {}; for (var prop in object ){ if (!object.hasOwnProperty(prop)){ continue; } if (typeof(object[prop]) == 'object'){ continue; } if (typeof(object[prop]) == 'function'){ continue; } simpleObject[prop] = object[prop]; } return JSON.stringify(simpleObject); // returns cleaned up JSON };
我通常使用circular-json npm包来解决这个问题。
// Felix Kling's example var a = {}; ab = a; // load circular-json module var CircularJSON = require('circular-json'); console.log(CircularJSON.stringify(a)); //result {"b":"~"}
在尝试使用jQuery构建下面的消息时,我遇到了同样的错误。 将reviewerName
错误地分配给msg.detail.reviewerName
时,会发生循环引用。 JQuery的.val()修复了这个问题,看最后一行。
var reviewerName = $('reviewerName'); // <input type="text" id="taskName" />; var msg = {"type":"A", "detail":{"managerReview":true} }; msg.detail.reviewerName = reviewerName; // Error msg.detail.reviewerName = reviewerName.val(); // Fixed
我在NodeJS上解决这个问题是这样的:
var util = require('util'); // Our circular object var obj = {foo: {bar: null}, a:{a:{a:{a:{a:{a:{a:{hi: 'Yo!'}}}}}}}}; obj.foo.bar = obj; // Generate almost valid JS object definition code (typeof string) var str = util.inspect(b, {depth: null}); // Fix code to the valid state (in this example it is not required, but my object was huge and complex, and I needed this for my case) str = str .replace(/<Buffer[ \w\.]+>/ig, '"buffer"') .replace(/\[Function]/ig, 'function(){}') .replace(/\[Circular]/ig, '"Circular"') .replace(/\{ \[Function: ([\w]+)]/ig, '{ $1: function $1 () {},') .replace(/\[Function: ([\w]+)]/ig, 'function $1(){}') .replace(/(\w+): ([\w :]+GMT\+[\w \(\)]+),/ig, '$1: new Date("$2"),') .replace(/(\S+): ,/ig, '$1: null,'); // Create function to eval stringifyed code var foo = new Function('return ' + str + ';'); // And have fun console.log(JSON.stringify(foo(), null, 4));
这可能不是相关的答案,但是这个链接在JavaScript中检测和修复循环引用可能有助于检测导致循环依赖的对象 。
我得到了与jqurty formvaliadator相同的错误,但是当我删除了一个console.log内成功:函数,它的工作。