You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSDOM 11.6.0与Sinon假定时器触发无限循环,如何规避?

解决JSDOM 11.6.0搭配Sinon假定时器触发无限循环的问题

这个坑我之前踩过,核心原因是JSDOM在初始化过程中依赖真实的定时器机制,而Sinon的useFakeTimers()会完全覆盖原生的setTimeout、setInterval等方法,导致JSDOM内部的初始化逻辑陷入无限循环。

下面给你几个实用的解决办法:

方法一:调整加载顺序(最推荐)

最简单的思路就是先完成JSDOM的加载与初始化,再启用Sinon假定时器,让JSDOM初始化时用的是真实定时器,完全避开冲突:

// 先加载并初始化JSDOM
const jsdom = require('jsdom');
const dom = new jsdom.JSDOM('<!DOCTYPE html><p>Test DOM</p>');
global.window = dom.window;
global.document = dom.window.document;

// 之后再启用Sinon假定时器
const sinon = require('sinon');
sinon.useFakeTimers();

方法二:临时恢复真实定时器(适配必须先开假定时器的场景)

如果你的业务逻辑要求必须先启用假定时器,可以在加载JSDOM前临时恢复原生定时器,完成JSDOM初始化后再重新启用假定时器:

const sinon = require('sinon');

// 先启用假定时器并保存实例
const clock = sinon.useFakeTimers();

// 临时恢复原生定时器
clock.restore();

// 加载并初始化JSDOM
const jsdom = require('jsdom');
const dom = new jsdom.JSDOM('<!DOCTYPE html><p>Test DOM</p>');
global.window = dom.window;
global.document = dom.window.document;

// 重新启用假定时器
sinon.useFakeTimers();

方法三:限制Sinon假定时器的覆盖范围(部分场景适用)

你可以让Sinon只覆盖你需要用到的定时器方法,避免影响JSDOM的依赖逻辑。比如只覆盖setTimeout,保留原生的setInterval(这个需要根据实际测试需求调整,不一定适配所有场景):

const sinon = require('sinon');

// 仅覆盖指定的定时器方法
sinon.useFakeTimers({
  toFake: ['setTimeout']
});

// 再加载JSDOM
const jsdom = require('jsdom');

额外提醒:如果测试中需要操作JSDOM环境内的定时器,建议在JSDOM初始化完成后,单独覆盖JSDOM窗口内的定时器方法,而不是一开始就覆盖全局定时器。

内容的提问来源于stack exchange,提问作者Sergio Cinos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:39:37