How do you call a function every second in a Chrome Extension Manifest V3 Background Service Worker?

Service workers replace background pages in Manifest v3 Google Chrome Extensions, and I’m trying to use one for my extension. The documentation says timers (setTimeout and setInterval) should be avoided because timers get canceled when service workers terminate (which may happen at any time). Unlike background pages, service workers can’t be persistent and will always be subject to termination. The documentation recommends using the Alarms API instead.

I need to be able to run a function periodically in a Manifest v3 service worker, but alarms don’t suit my use case because they’re slow. The shortest allowed alarm duration is 1 minute, but I want to run a function in shorter intervals—a second or a few seconds.

I tried using event.waitUntil to keep the service worker alive per this Stack Overflow answer. Here’s my attempted solution at mimicking a 1-second setInterval with repeating waitUntil calls:

var e;

function doThisEachSecond(resolver) {

    console.log('running function')

    // … CODE …

    e.waitUntil(new Promise(resolve => setTimeout(() => {doThisEachSecond(resolve);}, 1000)));
    resolver();
}

self.onactivate = event => {

    event.waitUntil(new Promise(resolve => {
        e = event;
        doThisEachSecond(resolve);
    }));

    console.log('activated');
};

It has big problems :

Since event.waitUntil makes the event dispatcher wait, these events don’t fire when my bootleg setInterval is running:

chrome.tabs.onUpdated.addListener(…);
chrome.tabs.onReplaced.addListener(…);
chrome.runtime.onMessage.addListener(…);

And I found that doThisEverySecond eventually stops getting called if the service worker is left to run for some time like a few minutes. When this occurs, the events that queued up during waitUntil periods fire all at once.

Looks like my approach isn’t the way to go.

How do you call a function every second in a Chrome Extension Manifest V3 Background Service Worker?