我有以下内容...

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时抛出以下错误。

br />

评论

您正在尝试发送一个具有循环引用的对象。什么是pagedoc?

我的意思是什么? 1. pagedoc的价值是什么? 2.循环引用:a = {}; a.b = a;

啊..解决了!如果您想回答这个问题,我会为您效劳的!

尝试使用node.js:util.inspect

我遇到了这个问题,原因是它忘记了在异步函数中等待以获取函数的值。

#1 楼

这意味着您在请求中传递的对象(我想它是pagedoc)具有循环引用,类似于: br />
NB:DOM节点就是这种情况,它们具有循环引用,即使它们未附加到DOM树也是如此。每个节点都有一个JSON.stringify,在大多数情况下,它指的是ownerDocumentdocument至少通过document引用了DOM树,而document.body再次引用了document.body.ownerDocument,这只是DOM树中的多个循环引用之一。

评论


谢谢!这解释了我遇到的问题。但是,DOM对象中存在的循环引用如何不会引起任何问题? JSON是否可以将文档对象字符串化?

– asss
13年4月24日在6:06

@asgs:至少在Chrome中确实会导致问题。 Firefox似乎对此更聪明,但我不知道它在做什么。

–费利克斯·克林(Felix Kling)
13-4-24在6:08



是否可以“捕获”此错误并进行处理?

– Doug Molineux
2015年11月11日在21:47

@DougMolineux:当然,您可以使用try ... catch捕获此错误。

–费利克斯·克林(Felix Kling)
2015年11月11日在21:49

@FelixKling不幸的是我无法正常工作(可能做错了什么),我最终使用了这个:github.com/isaacs/json-stringify-safe

– Doug Molineux
2015年11月13日在20:22

#2 楼

根据Mozilla的JSON文档,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次迭代后仍然抛出异常。尽管如此,如果您确实需要它,可以在顶层获得对象的良好表示就足够了。也许有人可以对此进行改进?在用于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随时进行改进/贡献!

评论


这是我第一次看到要传递的函数,该函数返回一个自执行函数,该函数返回一个常规函数。我相信我理解为什么这样做,但是我不相信自己会找到该解决方案,而且我认为如果我能看到需要此设置的其他示例,我会更好地记住该技术。话虽这么说,您能指出有关此设置/技术(缺乏更好的单词)或类似文献的任何文献吗?

–肖恩
2012年6月24日在2:14



+1肖恩。请删除该IEFE,它绝对没有用而且难以辨认。

–贝尔吉
13年3月22日在12:40

指出检查器arg的thx!它允许调试循环问题。就我而言,我有一个jquery数组,我想拥有一个普通数组。它们在调试打印模式下看起来都相似。关于IEFE,我看到它们经常在绝对不需要它们的地方使用,并同意Shawn和Bergi的看法。

–citykid
13年4月7日在12:04



我不确定为什么,但是这种解决方案似乎对我不起作用。

– Nikola Schou
16年11月1日在12:11

@BrunoLM:对于30个迭代限制,如果返回'[Unknown:'+ typeof(value)+']',您将看到如何修复检查器以正确处理函数和某些其他类型。

– Alex Pakka
17年6月29日在15:54

#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
};


评论


对我来说是完美的答案。也许错过了“功能”关键字?

– Stepan Loginov
16年4月29日在8:52

#4 楼

我通常使用circular-json npm包来解决此问题。 :

// Felix Kling's 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/flatted

#5 楼

根据zainengineer的答案...另一种方法是对对象进行深层复制,并去除圆形引用,并对结果进行字符串化。

 function cleanStringify(object) {
    if (object && typeof object === 'object') {
        object = copyWithoutCircularReferences([object], object);
    }
    return JSON.stringify(object);

    function copyWithoutCircularReferences(references, object) {
        var cleanObject = {};
        Object.keys(object).forEach(function(key) {
            var value = object[key];
            if (value && typeof value === 'object') {
                if (references.indexOf(value) < 0) {
                    references.push(value);
                    cleanObject[key] = copyWithoutCircularReferences(references, value);
                    references.pop();
                } else {
                    cleanObject[key] = '###_Circular_###';
                }
            } else if (typeof value !== 'function') {
                cleanObject[key] = value;
            }
        });
        return cleanObject;
    }
}

// Example

var a = {
    name: "a"
};

var b = {
    name: "b"
};

b.a = a;
a.b = b;

console.log(cleanStringify(a));
console.log(cleanStringify(b)); 




#6 楼

这可能与答案无关,但是此链接检测并修复JavaScript中的循环引用可能有助于检测导致循环依赖性的对象。

#7 楼

我可以像这样在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, '{ : function  () {},')
    .replace(/\[Function: ([\w]+)]/ig, 'function (){}')
    .replace(/(\w+): ([\w :]+GMT\+[\w \(\)]+),/ig, ': new Date(""),')
    .replace(/(\S+): ,/ig, ': null,');

// Create function to eval stringifyed code
var foo = new Function('return ' + str + ';');

// And have fun
console.log(JSON.stringify(foo(), null, 4));


#8 楼

尝试使用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


#9 楼

我在使用jQuery formvaliadator时遇到了相同的错误,但是当我在success:函数中删除console.log时,它起作用了。

#10 楼

就我而言,当我在服务器端使用async函数来使用猫鼬获取文档时,遇到了该错误。原来原因是我在调用await方法之前忘了放find({})。添加该部分解决了我的问题。

评论


温馨提示:从jQuery 1.8开始,不推荐使用await / async-因此请不要使用它。

–adhg
7月27日14:16

#11 楼

这有效,并告诉您哪些属性是圆形的。它还允许使用引用

   JSON.stringifyWithCircularRefs = (function() {
    const refs = new Map();
    const parents = [];
    const path = ["this"];

    function clear() {
      refs.clear();
      parents.length = 0;
      path.length = 1;
    }

    function updateParents(key, value) {
      var idx = parents.length - 1;
      var prev = parents[idx];
      if (prev[key] === value || idx === 0) {
        path.push(key);
        parents.push(value);
      } else {
        while (idx-- >= 0) {
          prev = parents[idx];
          if (prev[key] === value) {
            idx += 2;
            parents.length = idx;
            path.length = idx;
            --idx;
            parents[idx] = value;
            path[idx] = key;
            break;
          }
        }
      }
    }

    function checkCircular(key, value) {
      if (value != null) {
        if (typeof value === "object") {
          if (key) { updateParents(key, value); }

          let other = refs.get(value);
          if (other) {
            return '[Circular Reference]' + other;
          } else {
            refs.set(value, path.join('.'));
          }
        }
      }
      return value;
    }

    return function stringifyWithCircularRefs(obj, space) {
      try {
        parents.push(obj);
        return JSON.stringify(obj, checkCircular, space);
      } finally {
        clear();
      }
    }
  })();
 


示例重新构造对象,其中包含许多消除噪音:

{
    "requestStartTime": "2020-05-22...",
    "ws": {
        "_events": {},
        "readyState": 2,
        "_closeTimer": {
            "_idleTimeout": 30000,
            "_idlePrev": {
                "_idleNext": "[Circular Reference]this.ws._closeTimer",
                "_idlePrev": "[Circular Reference]this.ws._closeTimer",
                "expiry": 33764,
                "id": -9007199254740987,
                "msecs": 30000,
                "priorityQueuePosition": 2
            },
            "_idleNext": "[Circular Reference]this.ws._closeTimer._idlePrev",
            "_idleStart": 3764,
            "_destroyed": false
        },
        "_closeCode": 1006,
        "_extensions": {},
        "_receiver": {
            "_binaryType": "nodebuffer",
            "_extensions": "[Circular Reference]this.ws._extensions",
        },
        "_sender": {
            "_extensions": "[Circular Reference]this.ws._extensions",
            "_socket": {
                "_tlsOptions": {
                    "pipe": false,
                    "secureContext": {
                        "context": {},
                        "singleUse": true
                    },
                },
                "ssl": {
                    "_parent": {
                        "reading": true
                    },
                    "_secureContext": "[Circular Reference]this.ws._sender._socket._tlsOptions.secureContext",
                    "reading": true
                }
            },
            "_firstFragment": true,
            "_compress": false,
            "_bufferedBytes": 0,
            "_deflating": false,
            "_queue": []
        },
        "_socket": "[Circular Reference]this.ws._sender._socket"
    }
}


要重建调用JSON.parse(),然后遍历属性以查找[Circular Reference]标签。然后将其切碎并...评估...将this设置为根对象。

不要评估任何可以被黑客入侵的东西。更好的做法是执行string.split('.'),然后按名称查找属性以设置引用。