Service Worker架构:高效令牌处理与网络请求同步实现

Service Worker架构:高效令牌处理与网络请求同步实现

本文探讨了在Service Worker中高效管理认证令牌的策略,特别是如何处理令牌的周期性更新以及确保所有网络请求都能同步获取并使用最新令牌。核心方案是利用JavaScript Promise的特性,通过替换Promise对象而非修改其状态,实现请求的等待与令牌的动态更新,并提供了健壮的错误处理机制。

在现代web应用中,尤其是在渐进式web应用(pwa)或使用trusted web activity (twa) 的原生应用场景下,service worker扮演着关键角色。它不仅能提供离线能力,还能拦截和处理网络请求,从而成为集中管理认证令牌的理想场所。然而,当认证令牌需要周期性更新时,如何确保所有并发的网络请求都能获取到最新的令牌,并且在令牌更新过程中能够优雅地等待,是一个需要精心设计的挑战。

挑战:Service Worker中的令牌管理与请求同步

设想一个场景:你的Web应用依赖于一个具有生命周期的认证令牌,该令牌每隔一定时间(例如15分钟)需要刷新。Service Worker负责:

首次启动时获取令牌并存储。拦截所有出站网络请求,并为它们附加此令牌。令牌过期前,周期性地刷新令牌。最重要的是,在令牌刷新期间,所有新的网络请求都必须等待新令牌的到来,然后才能继续执行,并使用这个新令牌。

最初,开发者可能会考虑使用某种“可变Promise”或Proxy对象来实现Promise的动态更新。然而,Promise一旦被resolve或reject,其状态就不可改变。试图直接修改一个已完成的Promise是徒劳的。解决方案的关键在于理解:我们不需要修改Promise本身,而是需要替换存储Promise的变量。

解决方案:基于Promise的令牌刷新与请求同步

核心思路是维护一个指向当前有效令牌Promise的变量。当需要刷新令牌时,我们创建一个新的Promise来代表令牌获取过程,并用这个新Promise替换掉旧的变量。所有依赖令牌的网络请求都将await这个变量所指向的Promise。

1. 令牌获取函数

首先,定义一个异步函数来负责实际的令牌获取逻辑。这个函数应该返回一个Promise,该Promise在令牌成功获取后解析为令牌字符串。

/** * 模拟异步获取认证令牌的函数。 * 实际应用中会包含API调用、错误处理等逻辑。 * @returns {Promise} 解析为认证令牌字符串的Promise。 */async function fetchAuthToken() {  console.log("正在获取新的认证令牌...");  // 模拟网络请求延迟  await new Promise(resolve => setTimeout(resolve, 1000));  const newToken = "Bearer_New_Auth_Token_" + Date.now();  console.log("令牌获取成功:", newToken);  return newToken;}

2. 令牌 Promise 管理

我们需要一个变量来存储当前的令牌Promise。在Service Worker启动时初始化它,并在令牌需要刷新时更新它。

let currentTokenPromise = null; // 用于存储当前认证令牌的Promise/** * 初始化或刷新认证令牌。 * 该函数会更新 currentTokenPromise 变量。 */async function initializeOrRefreshToken() {  console.log("开始初始化/刷新令牌...");  currentTokenPromise = fetchAuthToken(); // 创建一个新的Promise并赋值  try {    await currentTokenPromise; // 等待令牌获取完成    console.log("令牌已准备就绪或已刷新。");  } catch (error) {    console.error("令牌获取失败:", error);    // 错误处理:将 currentTokenPromise 设置为 null,以便后续请求可以触发重试    currentTokenPromise = null;    // 可以在这里实现更复杂的错误重试逻辑  }}// Service Worker启动时立即获取令牌initializeOrRefreshToken();// 设置定时器,每15分钟刷新一次令牌const TOKEN_REFRESH_INTERVAL = 15 * 60 * 1000; // 15分钟setInterval(() => {  console.log("定时刷新令牌触发...");  initializeOrRefreshToken();}, TOKEN_REFRESH_INTERVAL);

3. 网络请求集成

现在,任何需要认证令牌的网络请求都可以简单地await currentTokenPromise。如果currentTokenPromise已经解决,请求将立即获取令牌;如果它仍在等待令牌获取或刷新,请求将自动暂停,直到Promise解决。

/** * 发送一个需要认证令牌的网络请求。 * @param {RequestInfo} input - 请求的URL或Request对象。 * @param {RequestInit} [init] - 请求的选项。 * @returns {Promise} 响应Promise。 */async function sendAuthenticatedRequest(input, init = {}) {  // 如果 currentTokenPromise 为 null,说明令牌尚未初始化或上次获取失败,  // 此时应尝试重新初始化令牌。这提供了首次失败后的重试机制。  if (!currentTokenPromise) {    console.warn("currentTokenPromise 为空,尝试重新初始化令牌...");    await initializeOrRefreshToken(); // 尝试重新获取令牌    // 如果 initializeOrRefreshToken 再次失败,currentTokenPromise 仍为 null,    // 此时 await currentTokenPromise 将不会阻塞,而是直接执行下一步,    // 导致请求在没有令牌的情况下发送或抛出错误。    // 更好的做法是让 initializeOrRefreshToken 抛出错误,或返回一个拒绝的Promise。    if (!currentTokenPromise) {      throw new Error("无法获取认证令牌,请求无法发送。");    }  }  const token = await currentTokenPromise; // 等待令牌可用  console.log("使用令牌发送请求:", token);  // 克隆请求头并添加认证信息  const headers = new Headers(init.headers);  headers.set('Authorization', token);  return fetch(input, { ...init, headers });}// 示例:在Service Worker中拦截fetch事件并使用上述函数self.addEventListener('fetch', event => {  // 假设只有特定的API请求需要认证  if (event.request.url.startsWith('/api/')) {    event.respondWith(sendAuthenticatedRequest(event.request));  } else {    event.respondWith(fetch(event.request));  }});// 模拟客户端发起请求async function clientSideRequestExample() {  try {    console.log("客户端发起请求...");    const response = await fetch('/api/data'); // 客户端通过Service Worker发送请求    const data = await response.json();    console.log("请求成功,数据:", data);  } catch (error) {    console.error("请求失败:", error);  }}// 可以在 Service Worker 内部模拟调用,或者通过 postMessage 从主线程触发// clientSideRequestExample();

错误处理与健壮性考虑

上述方案已经包含了基本的错误处理,即在fetchAuthToken失败时将currentTokenPromise重置为null,并在下次sendAuthenticatedRequest调用时触发initializeOrRefreshToken进行重试。然而,这仍有改进空间:

拒绝的Promise: 如果fetchAuthToken失败,它会返回一个拒绝的Promise。currentTokenPromise将存储这个拒绝的Promise。这意味着后续所有await currentTokenPromise的请求都会立即抛出错误,直到下一次定时刷新或手动重试成功。这在某些情况下可能是期望的行为,但在其他情况下可能需要更精细的控制。重试策略: 当initializeOrRefreshToken失败时,简单地将currentTokenPromise设置为null并等待下一次请求触发重试,可能会导致短时间内大量请求失败。可以考虑实现指数退避(exponential backoff)等更复杂的重试机制,或者在initializeOrRefreshToken内部进行多次重试。避免死锁: 确保fetchAuthToken本身不会依赖于sendAuthenticatedRequest,以避免循环依赖和潜在的死锁。令牌获取通常是一个独立的网络请求,不应被Service Worker的拦截逻辑所影响。Service Worker生命周期: Service Worker可能会在不活动一段时间后被浏览器终止。当它重新启动时,currentTokenPromise会重置,initializeOrRefreshToken将再次被调用。这与我们的设计是兼容的。

总结

通过简单地替换存储Promise的变量,而不是试图修改Promise本身,我们可以优雅地解决Service Worker中认证令牌的动态更新和网络请求同步问题。这种方法利用了JavaScript Promise的内置特性,使得代码简洁、逻辑清晰。结合健壮的错误处理和重试机制,可以构建一个高效且可靠的Service Worker令牌管理系统,从而提升Web应用的性能和用户体验。

以上就是Service Worker架构:高效令牌处理与网络请求同步实现的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1525913.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
如何实现一个基于Canvas的2D游戏引擎?
上一篇 2025年12月20日 18:04:52
如何优化JavaScript包的体积以提升应用加载速度?
下一篇 2025年12月20日 18:05:03

相关推荐

  • Canva的AI混合工具如何操作?快速设计专业图形与文本的步骤

    Canva的AI混合功能通过Magic Studio将文本、图像生成与智能设计整合,提升创作效率。首先,使用Magic Write生成文案初稿,克服空白页难题;其次,通过Magic Media输入详细描述生成定制化图像,越具体效果越好;再利用Magic Design上传图片或输入文字自动生成多种设计…

    2026年9月22日
    000
  • PHPRestfulAPI怎么开发_PHP构建高效安全的RestfulAPI教程

    答案:本文介绍如何用PHP构建高效安全的Restful API,涵盖设计规范、项目结构、数据库操作、安全机制、统一响应格式及性能优化。遵循Restful风格使用标准HTTP方法与状态码,通过index.php统一入口路由请求至控制器;采用PDO预处理防止SQL注入,结合JWT实现认证授权,确保输入验…

    2026年9月22日
    000
  • CentOS7搭建个人站点

    CentOS7搭建个人站点CentOS7搭建个人站点CentOS7搭建个人站点CentOS7搭建个人站点

    在本文中,我们将指导您在centos7系统上使用httpd搭建个人网站。httpd是apache http服务器的主程序,设计为一个独立运行的后台进程,负责建立处理请求的子进程或线程池。 首先,我们需要通过rpm命令检查系统中是否已安装httpd: rpm -qa | grep httpd 如果执行…

    2026年9月22日 用户投稿
    200
  • MySQL服务无法启动怎么办?常见解决方法

    MySQL服务无法启动怎么办?常见解决方法MySQL服务无法启动怎么办?常见解决方法MySQL服务无法启动怎么办?常见解决方法MySQL服务无法启动怎么办?常见解决方法

    mysql服务无法启动常见原因包括配置错误、端口占用、数据文件损坏或权限问题。解决方法如下:1. 查看错误日志,定位问题根源;2. 检查配置文件是否存在语法错误或路径问题;3. 确认端口(如3306)未被占用;4. 核查数据目录的权限与完整性;5. 必要时修复或重置数据目录,甚至重新安装mysql。…

    2026年9月22日 用户投稿
    000
  • Java TreeMap如何自定义排序规则

    TreeMap默认按键的自然顺序排序,可通过构造函数传入Comparator自定义排序规则。例如字符串可按长度排序:TreeMap map = new TreeMap((s1, s2) -> s1.length() – s2.length()); 对自定义对象如Person可按年龄…

    2026年9月22日
    000
  • 如何使用MLflow训练AI大模型?模型管理与跟踪的实用教程

    如何使用MLflow训练AI大模型?模型管理与跟踪的实用教程如何使用MLflow训练AI大模型?模型管理与跟踪的实用教程如何使用MLflow训练AI大模型?模型管理与跟踪的实用教程如何使用MLflow训练AI大模型?模型管理与跟踪的实用教程

    MLflow通过实验跟踪、可复现的项目封装、标准化模型格式和集中式模型注册表,实现大模型训练的全流程管理。它记录超参数、指标和模型文件,支持分布式环境下的集中日志管理,利用远程跟踪服务器和云存储统一收集数据,并通过模型版本控制与阶段管理提升团队协作与部署效率。 ☞☞☞AI 智能聊天, 问答助手, A…

    2026年9月22日 用户投稿
    000
  • qq浏览器怎么设置信任此站点_QQ浏览器添加信任站点设置方法

    可通过设置中心或地址栏将网站添加为可信站点以解除QQ浏览器限制。首先打开QQ浏览器,点击菜单进入设置,选择“隐私与安全”中的“可信站点管理”,添加并保存目标网址;也可在访问页面时点击地址栏锁形图标,通过站点设置直接设为可信;若需临时访问,可在安全警告页点击“继续访问”或“仍然前往”实现临时放行,但不…

    2026年9月22日
    300
  • Java Collections.synchronizedList方法如何保证线程安全

    synchronizedList通过同步方法保证线程安全,使用synchronized关键字对每个操作加锁,确保单个操作的原子性;但迭代或复合操作需手动同步,否则可能引发并发异常;其性能较低,适用于读多写少、并发不高的场景,高并发下推荐使用CopyOnWriteArrayList。 Java 中 C…

    2026年9月22日
    100
  • 如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程

    如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程

    MiniTool MovieMaker虽无AI生成功能,但可高效编辑AI生成的MP4、MOV等格式视频或图片序列。通过导入素材后,利用其剪辑、过渡、滤镜、文字、音频处理等功能,实现AI片段的精剪、色彩统一、无缝衔接与风格化输出。支持主流视频、图片及音频格式,兼容性好,适合个人创作者进行AI内容后期整…

    2026年9月22日 用户投稿
    500
  • VSCode如何调试JavaScript代码 VSCode调试功能的实战技巧

    要在vscode中调试javascript,首先需设置断点、配置launch.json文件、选择合适的调试环境并启动调试会话;2. launch.json至关重要,常见陷阱包括program路径错误、type类型不匹配、cwd设置不当、混淆launch与attach模式以及source map配置缺…

    2026年9月22日
    000
  • safari浏览器如何阻止网站访问我的运动和方向数据_safari浏览器阻止网站访问运动方向数据

    首先关闭Safari对网站的运动与方向传感器权限,进入设置- Safari -网站-运动与方向,将默认行为设为拒绝;其次可针对特定网站单独管理权限,阻止可疑站点访问传感器;最后启用无痕浏览模式以增强隐私保护,限制网页对硬件的持续访问。 如果您在使用 Safari 浏览器时发现某些网站试图获取您的设备…

    2026年9月22日
    100
  • 京东外卖店铺能变更营业执照吗?京东外卖店铺能变更营业执照吗怎么办

    京东外卖店铺变更经营主体需先确认资格并准备材料,如营业执照、法人身份证、品牌授权书等,确保店铺运营满一年且无重大违规;随后登录商家后台提交申请,填写新主体信息并上传文件;等待平台1-3个工作日审核,通过后进入7天公示期;公示无异议后,完成线下工商变更并更新银行账户信息,最后在后台上传新证照,待平台确…

    2026年9月22日
    400
  • 喵趣漫画官网登录页面 喵趣漫画免费阅读全本漫画

    喵趣漫画官网登录页面位于其官方网站https://www.miaoqumanhua.com/,用户可直接通过浏览器访问并登录账号。 喵趣漫画官网登录页面在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来喵趣漫画免费阅读全本漫画的相关信息,感兴趣的网友一起随小编来瞧瞧吧! https://ww…

    2026年9月22日
    000
  • 中国联通正式获得开展 eSIM 手机运营服务商用试验的批复

    感谢网友 会弹琴的九号、学士 的线索投递! 10月13日,三大运营商官方微信号相继发布消息,宣告eSIM服务进入新阶段。其中,中国联通于当日上午10:00率先发布推文《抢约!联通eSIM来了!》,动作迅速,展现出强烈的市场积极性;中国移动在傍晚19:29发布《中国移动全面上线eSIM手机办理》;而中…

    2026年9月22日
    200
  • 为什么建议手动定义Java序列化ID

    手动定义serialVersionUID可确保序列化兼容性,避免因类结构变化导致反序列化失败。Java默认生成的ID依赖类名、字段等信息,编译环境或代码微小改动均使其改变,易引发InvalidClassException。显式声明后,可在兼容性变更时主动控制ID更新,保留原ID则允许旧版本读取新对象…

    2026年9月22日
    200
  • mysql怎么使用全文索引 mysql创建全文索引的配置方法

    mysql怎么使用全文索引 mysql创建全文索引的配置方法mysql怎么使用全文索引 mysql创建全文索引的配置方法mysql怎么使用全文索引 mysql创建全文索引的配置方法mysql怎么使用全文索引 mysql创建全文索引的配置方法

    mysql使用全文索引的核心是让数据库像搜索引擎一样理解并高效检索文本内容。1. 创建全文索引:可在建表时或之后通过alter table语句为char、varchar或text字段添加fulltext索引;2. 使用match against查询:支持自然语言模式(自动过滤停用词并按相关性排序)和…

    2026年9月22日 用户投稿
    100
  • VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​

    VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​

    vscode中高效批量追踪数据变化的关键是将监视列表用作表达式求值器,而非仅添加单一变量;2. 可在监视列表中添加复杂对象路径(如user.profile.address.city)、计算表达式(如(a + b) * c)、函数调用(如calculatetotal(items))或条件判断(如myv…

    2026年9月22日 用户投稿
    000
  • 在Java中如何统计List中元素出现次数

    答案是使用Map或Stream API统计List元素频次最高效。通过HashMap手动遍历统计,或用Java 8的Stream结合groupingBy和counting()实现简洁计数,Collections.frequency适用于小数据量但性能较差,推荐Stream方式兼顾性能与可读性。 在J…

    2026年9月22日
    900
  • 如何设置Linux服务超时参数 systemd服务超时配置

    如何设置Linux服务超时参数 systemd服务超时配置如何设置Linux服务超时参数 systemd服务超时配置如何设置Linux服务超时参数 systemd服务超时配置如何设置Linux服务超时参数 systemd服务超时配置

    systemd服务超时参数调整方法包括:1.使用systemctl show查看timeoutstartsec、timeoutstopsec、timeoutsec字段获取当前配置;2.通过systemctl edit编辑unit文件设置timeoutstartsec、timeoutstopsec或t…

    2026年9月22日 用户投稿
    000
  • 360浏览器如何切换极速模式

    在浏览网页时,想要获得更流畅、更快速的上网体验,许多用户都希望将360浏览器切换至极速模式。那么具体该如何操作呢?以下是几种简单有效的方法。 方法一:通过地址栏图标一键切换 打开360浏览器后,留意地址栏右侧,会看到一个闪电图标和一个书本图标的组合。其中,闪电代表极速模式,书本则代表兼容模式。只需点…

    2026年9月22日
    100

发表回复

登录后才能评论
关注微信