【问题标题】:Debouncing asynchronous work inside of a service worker's event handler在 Service Worker 的事件处理程序中去抖动异步工作
【发布时间】:2025-11-30 04:45:01
【问题描述】:

在 ServiceWorker 中使用 lodash debounced 函数对于 Firefox 来说是可以的。它们等待分配的超时时间,如果再次调用去抖函数,则计时器会重置。

但是,对于 Chrome,没有什么能按预期工作:去抖函数一调用就会调用内部函数,并且不会等待计时器中的重置。

有人遇到过这个问题吗?有什么解决方法吗?

我正在使用它来等待空闲用户(一段时间内不再获取)发送记录的分析。

【问题讨论】:

    标签: cross-browser lodash service-worker debounce


    【解决方案1】:

    在不查看示例代码的情况下完全调试它有点困难,但一般的经验法则是,如果您要在服务工作线程事件处理程序的同步执行之外调度您想要完成的异步工作,您需要

    • ExtendableEvent 内部安排工作和
    • 通过将完成工作的承诺传递给ExtendableEventwaitUntil() 方法来包装工作。

    FetchEventExtendableEvent。)

    如果你没有这样做,那么浏览器不能保证你的异步任务会在服务工作线程被杀死之前完成。不同的浏览器或多或少会主动终止服务工作线程,因此这可能解释了您所看到的不同行为。

    lodash 的 debounce() 不提供对 Promise 的内置支持,因此您要么必须 wrap things yourself,要么找到合适的替代库。请注意,无论您使用哪种方法,请确保您使用最终会解决的承诺,即使操作已消除抖动。否则,如果你传递了一个无法解析为 waitUntil() 的 promise,你最终会让 service worker 存活太久。

    抛开承诺返回debounceWithPromises() 的实际实现,一般结构如下所示:

    self.addEventListener('fetch', (event) => {
      if (/* some criteria is met */) {
        // As soon as the promise passed to respondWith() resolves,
        // the response will start being fed to the client.
        event.respondWith(generateResponse(event);
    
        // Independent of the response generation, the promise returned
        // by the hypothetical debounceWithPromises() will keep the
        // service worker alive until it resolves or rejects (or until a
        // browser-specific maximum lifetime is reached).
        event.waitUntil(debounceWithPromises(logStats));
      }
    });
    

    【讨论】:

    • 现在一切都说得通了,但我认为被杀死的 serviceworker 最终不会发送分析数据,而是跳过等待时间
    • 我不能 100% 确定这种行为差异,但依靠 event.waitUntil() 处理这类事情仍然很重要。
    最近更新 更多