Service Workers
前言
Service Workers 是浏览器平台中的一个相对较新的功能。它们的核心是提供一个单独的JavaScript执行上下文,该上下文可以拦截(并可能修改)主要执行上下文生成的所有网络流量。本质上,它们是浏览器中存在的代理层,位于主应用程序代码与其调用的网络端点之间。
使用详解
// This is how service workers intercept network request events -
// every network request made by the application code will trigger
// this event listener.
// 这就是服务工作人员拦截网络请求事件的方式——应用程序代码发出的每个网络请求都将触发这个事件侦听器。
self.addEventListener("fetch", (event) => {
// By the time this event listener is called, the service worker should
// already have been configured to watch for requests to particular servers.
// 在调用此事件侦听器时,服务工作人员应该已经配置为监视对特定服务器的请求。
if (self.appAuthConfig &&
typeof self.appAuthConfig.resourceServers === "object" &&
Object.keys(self.appAuthConfig.resourceServers).length) {
// Check to see if this particular network request event
// is to one of the configured resource servers.
// 检查此特定网络请求事件是否指向已配置的资源服务器之一。
var resourceServer = Object.keys(self.appAuthConfig.resourceServers)
.filter((rs) => event.request.url.indexOf(rs) === 0)[0];
if (resourceServer) {
// This is how service workers alter the response that is
// presented to the application code - You can resolve the
// promise passed into `respondWith` with any Response object.
// 这就是服务工作人员更改呈现给应用程序代码的响应的方式——您可以用任何响应对象解析传递到‘respondWith’的承诺。
// https://developer.mozilla.org/en-US/docs/Web/API/Response
event.respondWith(new Promise((resolve, reject) => {
// Modify the current request by adding the appropriate
// access token to it.
// 通过添加适当的访问令牌来修改当前请求。
self.addAccessTokenToRequest(event.request, resourceServer)
// Make the token-bearing request to the resource server.
// 向资源服务器发出带有令牌的请求。
.then((rsRequest) => fetch(rsRequest))
.then((resp) => {
// Check for the special-case error that we can possibly recover from.
// 检查特殊情况的错误,我们可以恢复。
if (!resp.ok && getAuthHeaderDetails(resp.headers)["error"] === "invalid_token") {
/*
From https://tools.ietf.org/html/rfc6750#section-3.1:
invalid_token
The access token provided is expired, revoked, malformed, or
invalid for other reasons. The resource SHOULD respond with
the HTTP 401 (Unauthorized) status code. The client MAY
request a new access token and retry the protected resource
request.
提供的访问令牌已过期、撤消、格式错误或因其他原因无效。资源应该使用HTTP 401(未授权)状态码响应。客户端可以请求新的访问令牌并重试受保护的资源请求。
We are going to follow the advice of the RFC here and try to request a new
access token and retry the request.
我们将遵循RFC的建议,尝试请求一个新的访问令牌,然后重试该请求。
*/
let promise = self.waitForRenewedToken(resourceServer)
.then(() => self.addAccessTokenToRequest(event.request, resourceServer))
.then((freshRSRequest) => fetch(freshRSRequest));
// The act of obtaining a fresh token is done outside
// of the service worker. Use a MessageChannel to signal
// the main execution context that a fresh token is needed.
// 获取新令牌的操作是在服务工作人员之外完成的。使用消息机制向主执行上下文发出需要新标记的信号。
// https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel
self.messageChannel.postMessage({
"message": "renewTokens",
"resourceServer": resourceServer
});
return promise;
} else {
return resp;
}
})
.then(resolve, reject);
}));
}
}
return;
});