Учитывая следующий код:
let id = setInterval(function f() {console.info("Nice.");}, 1000);
console.info(id);
JSON.stringify(id);
Это заканчивается ошибкой в последней строке с сообщением TypeError: Converting circular structure to JSON.
console.info(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 содержит циклическую ссылку?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Объект тайм-аута содержит ссылку на себя (доступ к которой можно получить с помощью id.ref())
Вы можете увидеть это в выводе console.info():
TimersList {
_idleNext: [Circular],
_idlePrev: [Circular],
_timer: Timer { '0': [Function: listOnTimeout], _list: [Circular] },
_unrefed: false,
msecs: 1000,
nextTick: false },
_idleNext:
Вы не можете сериализовать его с помощью JSON.stringify(), потому что объект содержит ссылку на себя, и этот объект также содержит ссылку на себя, и этот объект также содержит ссылку на себя (см., Куда я иду?)
Да, я видел там Circular. Мой главный вопрос: Зачем?
@ kramer65 Я обновил свой вопрос. По сути, невозможно сериализовать какой-либо объект, содержащий ссылку на себя.
Я понимаю это, но мой вопрос был больше: почему он содержит ссылку на себя? В чем причина этой циркулярной ссылки?
Обратите внимание, что setInterval в node.js ведет себя иначе, чем setInterval в javascript. Хотя версия javascript возвращает целое число, node.js возвращает объект Timeout. и не предназначена для сериализации.
Если вы хотите «сериализовать» объект тайм-аута, вы можете использовать вспомогательный класс, как показано ниже. Это будет сериализовать таймауты, сохраняя их во внутреннем поле TimeoutHelper.timeouts, и вернет идентификатор, который вы позже можете вызвать с помощью 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.info('test'), 1000);
console.info(`Serialized TimeoutHelper id: ${i}`);
setTimeout(() => {
console.info(`Clearing Timeout: ${i}`);
TimeoutHelper.clearTimeout(i);
}, 5000);
Зачем вы его JSON.stringify?