我想使用 Service Workers 来增强现有网站。特别是,我想通过在实际资源不可用时让 Service Workers 使用占位符资源响应请求来添加更好的离线支持。这种方法一直有效,但我遇到了障碍。网站中有几个地方使用synchronousXHR 请求来加载某些资源,而我的 Service Worker 在 Chrome 中没有收到它们的事件。 (请不要建议消除同步 XHR 请求。这是期望的,但超出了范围。)
Service Worker 是否可以响应同步 XHR 请求?我可以想象这实施起来很复杂,并且如果不支持它也会理解。 W3C Service Workers 规范(工作草案) 和 WHATWG Fetch 规范(生活标准) 之间应该存在一个“正确”的答案,但我还没有完成对它们的解读。我希望能解释一下规范如何描述是否应该支持这一点,和/或对有关指定或实现此行为的讨论的任何引用。
是的,Service Worker 应该能够响应同步 XHR 请求。规范中没有明确说明这一点,但没有例外会导致同步 XHR 请求被区别对待,并且 W3C Web 平台测试 (WPT) 套件有一个测试用例来验证它是否受支持:
wpt/service-workers/service-worker/fetch-request-xhr-sync.https.html
.
Service Worker 只能响应来自 Firefox 和 Edge 之前的 Chromium 版本中主线程的同步 XHR 请求。它不适用于 Chrome、Safari 或当前版本的 Edge 和其他 Chromium 浏览器。 Chromium 曾经打算支持它,但五年后,仍然没有实现。
可在 WPT.fyi 获取最新的浏览器支持矩阵。您可以在自己的浏览器中运行 WPT 测试用例,网址为 https://w3c-test.org/service-workers/service-worker/fetch-request-xhr-sync.https.html.
所有浏览器似乎都支持 Service Workers 来处理从其他线程(例如 Web Workers)发送的同步 XHR 请求,但没有特定的 WPT 测试来验证这一点。
XMLHttpRequest规范,同步和异步请求的获取过程是相同,所以理论上,它应该被拦截,但是同步XHR已被弃用所以我不希望Chrome修复这个问题.
// 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();
这只是一个例子。我认为 Promise 可以很容易地链接起来(但垂直堆叠,而不是右缩进)以创建同步效果。