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 ,在大多数情况下它引用documentdocument至少通过document.bodydocument.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":"~"} 

https://www.npmjs.com/package/circular-json

在尝试使用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内成功:函数,它的工作。