服务工作线程是否可以响应同步 XHR 请求

Can Service Workers respond to synchronous XHR requests?

本文关键字:同步 XHR 请求 响应 线程 是否 服务工作      更新时间:2023-09-26

我想使用 Service Workers 来增强现有的网站。特别是,我想通过在实际资源不可用时使用占位符资源响应请求来添加更好的脱机支持。这种方法一直有效,但我遇到了一个障碍。站点中有几个位置使用同步 XHR 请求来加载某些资源,而我的 Service Worker 不会在 Chrome 中接收这些资源的事件。(请不要建议消除同步 XHR 请求。这是需要的,但超出了范围。

服务工作线程是否可以响应同步 XHR 请求?我可以想象这实现起来很复杂,如果不支持它会理解。W3C Service Workers规范(工作草案)和WHATWG Fetch规范(生活标准)之间应该存在一个"正确"的答案,但我还没有完成对它们的破译。我希望解释规范如何描述是否应该支持这一点,和/或对有关指定或实现此行为的讨论的任何引用。

理论上

是的,服务工作线程应该能够响应同步 XHR 请求。规范中没有明确说明这一点,但没有例外会导致同步 XHR 请求被区别对待,W3C Web 平台测试 (WPT) 套件有一个测试用例来验证它是否受支持:wpt/service-workers/service-worker/fetch-request-xhr-sync.https.html

实践中

截至 2019 年 1 月,服务工作者可以在 Firefox 和 Edge 中响应同步 XHR 请求,但不能在 Chrome 或 Safari 中响应。Chrome计划很快增加支持,但我们不知道Safari是否会增加支持。

最新的浏览器支持矩阵可在WPT.fyi上找到。您可以在自己的浏览器中运行 WPT 测试用例 https://w3c-test.org/service-workers/service-worker/fetch-request-xhr-sync.https.html。

根据XMLHttpRequest规范,同步和异步请求的获取过程是相同的,因此理论上应该对其进行拦截,但是Synchronous XHR已被弃用,因此我不希望Chrome解决此问题。

您可以通过将异步调用链接在一起来创建同步效果。它创建缩进回调 - 而承诺会使代码更易于阅读 - 但第二个 Ajax 调用直到第一个调用返回后才会进行。请注意,在两次调用中,第三个参数都设置为 true。

// Synchronized Ajax calls using 2 nested Asynchronous calls
// Asynchronous request #1 using traditional API
const axhr = new XMLHttpRequest();
axhr.open('GET', '/__so-example__', true);
axhr.onload = event => {
  console.log("A-XHR: " + axhr.responseText);
  // Asynchronous request #2 using traditional API
  const sxhr = new XMLHttpRequest();
  sxhr.open('GET', '/__so-example__', true);
  sxhr.onload = event => {
    console.log("S-XHR: " + sxhr.responseText);
  }
  sxhr.send();
}
axhr.send();

这只是一个例子。我认为承诺可以很容易地链接(但垂直堆叠,而不是右缩进)以创建同步效果。