Service Worker Architecture: 高效的令牌处理和网络请求同步

huangapple go评论73阅读模式
英文:

Service Worker Architecture: Efficient Token Handling and Network Request Synchronization

问题

TL;DR: 我需要一个机制来在服务工作线程中保存应用程序的身份验证令牌,该令牌将被网络请求使用。此令牌将定期更新(每15分钟)。如果当前正在获取令牌,则所有新的网络请求应等待令牌被获取,并使用新令牌的值。


> 我正在构建一个 Web 应用程序,其中身份验证是通过令牌处理的。由于这个应用程序只应该被用作本机应用程序(使用 TWA),我希望利用服务工作线程来处理网络请求。

要求:

  • 服务工作线程启动并首次获取令牌,并将其存储在内存中的变量中。
  • 网络请求使用此令牌进行授权。
  • 如果在获取令牌时进行了一些请求,它们应该等待令牌被获取,然后在令牌更新后继续。
  • 同样,在一定的短时间间隔后再次获取令牌时,应该发生相同的情况。令牌生命周期实际上被“重置”。

最接近的方法是使用 Promises,但由于 Promises 无法更新,我尝试使用 proxy 来实现这种效果。

这是我的尝试:使用 JavaScript 中的代理实现可更新的 Promises

最好的方法可能是使用某种修改过的“Observables”,但我还不完全理解它。

英文:

TL;DR: I need a mechanism to hold auth token for my application in a service worker, which will be used by network requests. This token will be updated periodically (15 min). If the token is currently being fetched, all the new network requests should wait for the token to be fetched, and use the new value of the token.


> I'm building an webapp in which authentication is handled via tokens. Since this application is only supposed to be used as a native app (using TWA), I wanted to utilize the service worker for handling network requests.

Requirements:

  • Service Worker boots up and fetches the token for the first time, and stores it in a variable in memory.
  • Network requests use this token for authorization.
  • If there were some requests made while the token was being fetched, they should wait for the token to be fetched, and then continue once the token is updated.
  • Similarly, the same should happen when the token is fetched again, after a certain short interval. The token life cycle is essentially reset.

The closest approach is to use Promises, but since promises can't be updated, I've tried using proxy to achieve this effect.

Here's my attempt at that: Updatable promises using proxy in JavaScript

It maybe best achieved with some modified form of 'Observables', but I don't fully understand it yet.

答案1

得分: 1

无需改变 promise 对象本身 - 一旦它锁定到一个值,它将保持不变。您只需将其替换为不同的 promise。网络请求将使用当前存储在变量中的 promise - 它可能已经被实现,或者在令牌更新时是待处理的 promise,因此它们只是等待它。

async function getToken() {  }
let tokenPromise = getToken();
setInterval(() => {
  tokenPromise = getToken();
}, 15*60*1000);
async function request() {
  const token = await tokenPromise;
  return fetch( token );
}

(还需要考虑错误处理,如果 getToken() 失败,它将存储一个拒绝的 promise 并阻止 request 在接下来的 15 分钟内工作。我建议将 tokenPromise = null 而不是这样,并在需要时重新尝试 getToken(),同时重新安排间隔。)

英文:

No need to mutate the promise object itself - which is impossible, once it's locked in to a value it will keep that. You can just replace it with a different promise. Network requests would use the promise currently stored in the variable - which is either already fulfilled, or a pending promise while the token is being updated, so they just wait for that.

async function getToken() { … }
let tokenPromise = getToken();
setInterval(() => {
  tokenPromise = getToken();
}, 15*60*1000);
async function request(…) {
  const token = await tokenPromise;
  return fetch(… token …);
}

<sub>(You also need to consider error handling, if getToken() fails it would store a rejected promise and prevent request from working for the next 15min. I'd put tokenPromise = null instead and re-try getToken() on the first request that needs it, also re-scheduling the interval.)</sub>

huangapple
  • 本文由 发表于 2023年5月30日 06:22:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76360616.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定