若浏览器存在session变量,如何避免重复发起fetch请求?
问题分析
你的代码出现阻塞/报错的核心原因有两个:
- 变量作用域问题:
phoneNum仅在if (!sessionStorage.getItem("country_code"))的代码块内定义,当session中已有country_code时,外部的await phoneNum.json()会触发phoneNum is not defined的错误,导致后续逻辑中断。 - 逻辑分支缺失:你没有处理“已有缓存的国家码时,如何获取电话数据”的分支,要么需要缓存电话数据,要么按需发起必要的请求。
修正方案
根据你“避免不必要API调用”的需求,提供两种常见场景的解决方案:
场景1:电话数据无需实时更新,可缓存到sessionStorage
如果/contacts/接口返回的是所有国家的电话列表且不需要实时刷新,可以把电话数据也缓存起来,彻底避免重复请求:
async function fetchCountryAndPhone() { // 先读取缓存的国家码和电话数据 let countryCode = sessionStorage.getItem("country_code"); let cachedPhone = sessionStorage.getItem("phone_data"); // 没有国家码时,请求/userinfo/获取并存储 if (!countryCode) { const countryRes = await fetch('/userinfo/'); const country = await countryRes.json(); countryCode = country.country_code.toLowerCase(); sessionStorage.setItem("country_code", countryCode); } // 没有缓存的电话数据时,请求/contacts/获取并存储(转成字符串存入session) if (!cachedPhone) { const phoneRes = await fetch('/contacts/'); const phoneData = await phoneRes.json(); cachedPhone = JSON.stringify(phoneData); sessionStorage.setItem("phone_data", cachedPhone); } // 把缓存的电话数据转成JSON对象后返回 return [JSON.parse(cachedPhone), countryCode]; } fetchCountryAndPhone().then(([phone, countryCode]) => { const getContactNum = phone[countryCode].sales; // 这里写你的后续业务逻辑 }).catch(error => console.warn(error));
场景2:电话数据需要实时更新,仅缓存国家码
如果/contacts/返回的数据需要实时获取,只需要跳过/userinfo/的请求,保留必要的/contacts/请求:
async function fetchCountryAndPhone() { let countryCode = sessionStorage.getItem("country_code"); // 没有国家码时才请求/userinfo/ if (!countryCode) { const countryRes = await fetch('/userinfo/'); const country = await countryRes.json(); countryCode = country.country_code.toLowerCase(); sessionStorage.setItem("country_code", countryCode); } // 实时请求最新的电话数据 const phoneRes = await fetch('/contacts/'); const phoneData = await phoneRes.json(); return [phoneData, countryCode]; } fetchCountryAndPhone().then(([phone, countryCode]) => { const getContactNum = phone[countryCode].sales; // 这里写你的后续业务逻辑 }).catch(error => console.warn(error));
关键修改说明
- 提升变量作用域:将
countryCode等变量放在函数顶部定义,避免块级作用域导致的未定义错误。 - 拆分缓存逻辑:明确区分“可缓存的接口(/userinfo/)”和“需实时请求的接口(/contacts/)”,按需跳过不必要的请求。
- 处理sessionStorage的字符串限制:sessionStorage只能存储字符串,因此缓存JSON数据时需用
JSON.stringify转换,读取时用JSON.parse还原。 - 简化后续逻辑:直接在函数内返回
countryCode,避免在回调中重复读取sessionStorage,代码更简洁。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

