Ошибка Chrome sendrequest: 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 ЗДЕСЬ", но, скорее всего, вызывает следующую ошибку при запуске chrome.extension.sendRequest
Uncaught TypeError: Converting circular structure to JSON
chromeHidden.JSON.stringify
chrome.Port.postMessage
chrome.initExtension.chrome.extension.sendRequest
suggestQuery
Кто-нибудь знает, что вызывает это?
Ответы
Ответ 1
Это означает, что объект, который вы передаете в запросе (я думаю, это pagedoc
) имеет круговую ссылку, что-то вроде:
var a = {};
a.b = a;
JSON.stringify
не может преобразовать такие структуры.
N.B.. Это будет иметь место с узлами DOM, которые имеют циклические ссылки, даже если они не привязаны к дереву DOM. Каждый node имеет ownerDocument
, который в большинстве случаев относится к document
. document
имеет ссылку на дерево DOM, по крайней мере, через document.body
и document.body.ownerDocument
снова ссылается на document
, что является лишь одной из нескольких циклических ссылок в дереве DOM.
Ответ 2
Как документы JSON в Mozilla, JSON.Stringify
имеет второй параметр censor
, который можно использовать для фильтрации/игнорирования дочерних элементов при разборе дерева. Однако, возможно, вы можете избежать круговых ссылок.
В 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 итераций. Тем не менее, это достаточно хорошо, чтобы получить достойное представление объекта на верхнем уровне, если вам это действительно нужно. Может быть, кто-то может улучшить это? В Node.js для объекта HTTP-запроса я получаю:
{
"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 Не стесняйтесь улучшать/вносить свой вклад!
Ответ 3
Один из подходов состоит в том, чтобы стричь объект и функции из основного объекта. И упростите более простую форму
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
};
Ответ 4
Я обычно использую пакет round-json npm для решения этой проблемы.
// Felix Kling example
var a = {};
a.b = a;
// load circular-json module
var CircularJSON = require('circular-json');
console.log(CircularJSON.stringify(a));
//result
{"b":"~"}
https://www.npmjs.com/package/circular-json
Ответ 5
Я разрешаю эту проблему в 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));
Ответ 6
У меня возникла такая же ошибка при попытке создать сообщение с помощью 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
Ответ 7
Это может быть не ответ, но эта ссылка Обнаружение и исправление циклических ссылок в JavaScript может оказаться полезной для обнаружения объектов, которые вызывают круговые зависимость.
Ответ 8
Я получал ту же ошибку с jqurty formvaliadator, но когда я удалил console.log внутри успеха: функция работала.