Navigator.locks报错:回调不可运行,Vue API服务并发问题排查
问题分析与解决办法
错误原因
你遇到的Failed to execute 'invoke' on 'LockGrantedCallback': The provided callback is no longer runnable.错误,本质是浏览器锁机制在授予锁时,发现对应的回调函数已经不可用(比如被垃圾回收、上下文丢失)。结合你的代码场景,核心问题出在每次调用myfunc时都会创建一个新的匿名箭头回调,当多个组件首次加载同时请求锁、等待队列较长时,早期创建的回调可能因JS垃圾回收机制被标记为不可用。
修复方案
1. 抽离回调逻辑为服务方法,保持回调引用稳定
把锁内部的逻辑抽成服务类的独立方法,避免每次调用myfunc都生成新的匿名函数,确保锁回调的引用始终有效:
class MyService { // ... 其他现有代码 // 抽离数据获取逻辑为独立方法 async _fetchDataIfNeeded() { if (isNil(store.data)) { await this.updateToken(); const response = await Get(dataUrl, this.token.accessToken); store.data = response.data; } } async myfunc() { // 用稳定的方法引用作为锁回调 await navigator.locks.request("data", () => this._fetchDataIfNeeded()); return store.data; } }
2. 添加错误捕获与重试机制
针对锁回调失效的异常,增加捕获逻辑并重试,避免因单次错误导致数据缺失:
async myfunc() { try { await navigator.locks.request("data", () => this._fetchDataIfNeeded()); } catch (err) { console.error("锁请求失败:", err); // 针对回调失效的错误进行重试 if (err.message.includes("no longer runnable")) { await navigator.locks.request("data", () => this._fetchDataIfNeeded()); } } return store.data; }
3. 验证updateToken的上下文正确性
确保updateToken方法的this指向正确的MyService实例:
- 如果
updateToken是类的普通方法,建议改为箭头函数定义,避免上下文丢失:updateToken = async () => { // 你的token更新逻辑 }
额外检查点
- 确认
store.data的初始化状态,确保首次调用时确实为nil,没有被其他逻辑提前修改 - 验证
Get请求的可靠性,排除因网络请求失败导致的数据缺失
内容的提问来源于stack exchange,提问作者Dremor
相关产品推荐
相关产品推荐

