考虑以下代码:
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 }
为什么超时对象包含循环引用?
答案 0 :(得分:2)
请注意,node.js中的setInterval
与javascript中的setInterval
行为不同。虽然javascript版本返回整数,但node.js returns a Timeout object.并不用于序列化。
答案 1 :(得分: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()
对其进行序列化,因为该对象包含对自身的引用,并且该对象也包含对自身的引用,并且该对象也包含对自身的引用(请参阅我要去的地方)在这里?)
答案 2 :(得分:1)
如果要“序列化”超时对象,则可以使用如下的帮助程序类。这将通过将超时存储在内部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);