mirror of
https://seed.radicle.dev/rad:z4D5UCArafTzTQpDZNQRuqswh3ury.git
synced 2026-10-18 19:10:45 +08:00
Stop the timer when resetting a dynamic interval
Resetting only forgot the key, so the pending timeout still fired and rescheduled itself: the sidebar kept reloading repos every 5 seconds after nothing was left to replicate, and after it unmounted.
This commit is contained in:
@@ -20,5 +20,6 @@ export function dynamicInterval(
|
||||
}
|
||||
|
||||
export function resetDynamicInterval(key: string) {
|
||||
clearTimeout(dynamicIntervals.get(key));
|
||||
dynamicIntervals.delete(key);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import { afterEach, beforeEach, expect, test, vi } from "vitest";
|
||||
|
||||
import { dynamicInterval, resetDynamicInterval } from "@app/lib/interval";
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetDynamicInterval("a");
|
||||
resetDynamicInterval("b");
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test("runs the callback once per period", () => {
|
||||
const callback = vi.fn();
|
||||
dynamicInterval("a", callback, 100);
|
||||
|
||||
vi.advanceTimersByTime(99);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
vi.advanceTimersByTime(1);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
vi.advanceTimersByTime(200);
|
||||
expect(callback).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
test("rescheduling a key replaces its callback and period", () => {
|
||||
const first = vi.fn();
|
||||
const second = vi.fn();
|
||||
dynamicInterval("a", first, 100);
|
||||
vi.advanceTimersByTime(50);
|
||||
dynamicInterval("a", second, 300);
|
||||
|
||||
vi.advanceTimersByTime(299);
|
||||
expect(first).not.toHaveBeenCalled();
|
||||
expect(second).not.toHaveBeenCalled();
|
||||
vi.advanceTimersByTime(1);
|
||||
expect(second).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("an async callback can reschedule its own key", async () => {
|
||||
const callback = vi.fn(async () => {
|
||||
await Promise.resolve();
|
||||
dynamicInterval("a", callback, 500);
|
||||
});
|
||||
dynamicInterval("a", callback, 100);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(100);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
await vi.advanceTimersByTimeAsync(499);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
await vi.advanceTimersByTimeAsync(1);
|
||||
expect(callback).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test("resetting a key stops its callback", () => {
|
||||
const callback = vi.fn();
|
||||
dynamicInterval("a", callback, 100);
|
||||
resetDynamicInterval("a");
|
||||
|
||||
vi.advanceTimersByTime(1000);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("keys run independently", () => {
|
||||
const a = vi.fn();
|
||||
const b = vi.fn();
|
||||
dynamicInterval("a", a, 100);
|
||||
dynamicInterval("b", b, 100);
|
||||
|
||||
vi.advanceTimersByTime(100);
|
||||
expect(a).toHaveBeenCalledTimes(1);
|
||||
expect(b).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
Reference in New Issue
Block a user