【问题标题】:Why does setInterval() give a circular reference?为什么 setInterval() 给出循环引用?
【发布时间】:2019-01-02 17:03:34
【问题描述】:

考虑以下代码:

let id = setInterval(function f() {console.log("Nice.");}, 1000);
console.log(id);
JSON.stringify(id);

最后一行出现错误TypeError: Converting circular structure to JSON

console.log(id) 给了

Timeout {
  _called: false,
  _idleTimeout: 1000,
  _idlePrev: 
   TimersList {
     _idleNext: [Circular],
     _idlePrev: [Circular],
     _timer: Timer { '0': [Function: listOnTimeout], _list: [Circular] },
     _unrefed: false,
     msecs: 1000,
     nextTick: false },
  _idleNext: 
   TimersList {
     _idleNext: [Circular],
     _idlePrev: [Circular],
     _timer: Timer { '0': [Function: listOnTimeout], _list: [Circular] },
     _unrefed: false,
     msecs: 1000,
     nextTick: false },
  _idleStart: 81,
  _onTimeout: [Function: f],
  _timerArgs: undefined,
  _repeat: 1000,
  _destroyed: false,
  [Symbol(asyncId)]: 6,
  [Symbol(triggerAsyncId)]: 1 }

为什么 Timeout 对象包含循环引用?

【问题讨论】:

  • 你为什么要 JSON.stringifying 它?

标签: javascript node.js typeerror circular-reference stringify


【解决方案1】:

Timeout object 包含对其自身的引用(可以使用 id.ref() 访问)

您实际上可以在console.log() 输出中看到它:

TimersList {
  _idleNext: [Circular],
  _idlePrev: [Circular],
  _timer: Timer { '0': [Function: listOnTimeout], _list: [Circular] },
  _unrefed: false,
   msecs: 1000,
   nextTick: false },
_idleNext: 

您不能使用JSON.stringify() 对其进行序列化,因为该对象包含对自身的引用,并且该对象还包含对自身的引用,并且该对象还包含对自身的引用(看看我要去哪里? )

【讨论】:

  • 是的,我在那里看到了Circular。我的主要问题是;为什么?
  • @kramer65 我已经更新了我的问题。基本上不可能序列化任何包含对自身的引用的对象
  • 我明白这一点,但我的问题更多:为什么它包含对自身的引用?循环引用的原因是什么?
【解决方案2】:

请注意,node.js 中的 setInterval 的行为与 javascript 中的 setInterval 不同。而 javascript 版本返回一个整数,node.js returns a Timeout object. 并且不用于序列化。

【讨论】:

    【解决方案3】:

    如果你想“序列化”你的超时对象,你可以使用如下的辅助类。这将通过将超时存储在内部 TimeoutHelper.timeouts 字段中来序列化超时,并返回一个 ID,您可以稍后使用 TimeoutHelper.clearTimeout(i) 调用它:

    let TimeoutHelper = (() => {
      let helper = {};
      let counter = 0;
      let timeouts = {};
      
      helper.setInterval = (fn, ms) => {
        let currCounter = counter++;
        
        timeouts[currCounter] = window.setInterval(fn, ms);
        
        return currCounter;
      }
      
      helper.clearTimeout = (id) => {
        if (typeof timeouts[id] === 'undefined') {
          return; // Mimic window.clearTimeout, and silently return if the ID doesn't exist
        }
        window.clearInterval(timeouts[id]);
        delete timeouts[id];
      }
      
      return helper;
    })();
    
    var i = TimeoutHelper.setInterval(() => console.log('test'), 1000);
    
    console.log(`Serialized TimeoutHelper id: ${i}`);
    
    setTimeout(() => {
      console.log(`Clearing Timeout: ${i}`);
      TimeoutHelper.clearTimeout(i);
    }, 5000);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-20
      • 2022-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-27
      • 1970-01-01
      • 2020-07-07
      相关资源
      最近更新 更多