了解Sinon时钟`tick`与`tickAsync`

问题描述 投票:0回答:1

我试图理解

clock.tick
clock.tickAsync
之间的区别以及我应该在哪里使用它们。文档中的解释对我来说并不清楚,通过查看代码本身,我仍然无法理解应该在何时何地使用每种方法。谁能帮我提供一个具体的代码示例?

javascript jestjs sinon clock
1个回答
3
投票

tickAsync() 还将中断事件循环,允许在运行计时器之前执行任何预定的 Promise 回调。

首先,我建议观看有关事件循环的视频

如果很短,

tick
tickAsync
之间的区别在于
tick
- 调用计时器同步
tickAsync
- 调用计时器异步,允许在调用计时器之前执行已解决的承诺

同步意味着什么。让我们看一下我们要测试的示例代码

function myFunction() {
  setTimeout(() => console.log('foo'), 1000)
  Promise.resolve().then(() => console.log('zoo'));
  console.log('bar')
}

以及我们的同步测试代码

it('should test synchronously', () => {
   myFunction()
   tick(1000); // This would call scheduled timers synchronously ⚠️
   console.log('baz')
});
// print 'bar'
// print 'foo'
// print 'baz'
// print 'zoo'

现在让我们看看相同的测试代码,但带有

tickAsync

it('should test synchronously', () => {
   myFunction()
   tickAsync(1000);
   console.log('baz')
});
// print 'bar'
// print 'baz' 👈
// print 'zoo' 👈
// print 'foo' 👈

如您所见,打印字符串的顺序发生了变化。 现在相同的代码,但带有

await

it('should test synchronously', async () => {
   myFunction()
   await tickAsync(1000);
   console.log('baz')
});
// print 'bar'
// print 'zoo' 👈
// print 'foo' 👈
// print 'baz' 👈

要理解顺序变化的原因,您应该了解微任务队列和常规队列之间的区别。但如果您观看了上面链接中的视频,您应该已经明白了😊

附注 另外,您应该了解

sinon.useFakeTimers();
将在自己的实现中替换
setTimeout
setInterval
,从而允许 sinon 完全控制传递给这些函数的计时器

这是一个非常粗略的近似 sinon

tick
&
tickAsync
如何实现

scheduledTimers = [];

function useFakeTimers() {
    global.setInterval = global.setTimeout = (fn) => {
        scheduledTimers.push(fn);
    }
}

function tick() {
    while (scheduledTimers.length) {
        scheduledTimers.shift()();
    }
}

function tickAsync() {
    // Call timers on the next tick
    return Promise.resolve().then(() => tick());
}
© www.soinside.com 2019 - 2024. All rights reserved.