Chrome扩展反复触发Unchecked runtime.lastError错误,sendResponse提前调用无法等待异步URL分析完成
Chrome扩展反复触发Unchecked runtime.lastError错误,sendResponse提前调用无法等待异步URL分析完成
兄弟,我太懂你这个头疼的问题了!本质上就是异步操作没等完就急着响应导致的——你的analyzePageGuest里用了fetch的链式.then(),这玩意儿是异步的,函数会直接跳过它继续往下走,结果sendResponse先执行了,等后面fetch的回调跑完再想处理就晚了,自然触发runtime.lastError。
给你一步步解决:
第一步:把异步逻辑改成async/await风格,让代码“等一等”
你已经把analyzePageGuest声明成async函数了,完全可以把.then()换成await,这样代码会老老实实等请求完成再继续,不会提前跑路:
async function analyzePageGuest(tabId, changeInfo, tab) { const url = tab.url; console.log('URL:', url); let analysisIdValue; try { const options = { method: 'POST', headers: { accept: 'application/json', 'x-apikey': '你的API密钥', // 别硬编码!后面说怎么存 'content-type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ url: url }), }; // 用await等待fetch请求完成,代替.then() const response = await fetch( 'https://www.virustotal.com/api/v3/urls', // 后面说去掉cors-anywhere的方法 options ); const responseData = await response.json(); console.log(responseData); analysisIdValue = responseData.data.id; // 假设你要拿这个分析ID // 如果还要查分析结果,继续用await const analysisResponse = await fetch( `https://www.virustotal.com/api/v3/analyses/${analysisIdValue}`, { method: 'GET', headers: { accept: 'application/json', 'x-apikey': '你的API密钥', }, } ); const analysisResult = await analysisResponse.json(); console.log('分析结果:', analysisResult); // 把结果返回给调用方 return analysisResult; } catch (error) { console.error('分析出错:', error); throw error; // 抛出错误让调用者处理 } }
第二步:处理消息监听/标签页触发逻辑,确保响应在异步完成后发送
如果是通过chrome.runtime.onMessage接收请求并响应,直接用async回调配合await就行,不用手动返回true(Chrome会自动识别Promise并等待):
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => { if (request.action === 'analyzePage') { try { // 等analyzePageGuest跑完再发响应 const result = await analyzePageGuest(sender.tab.id, {}, sender.tab); sendResponse({ success: true, data: result }); } catch (error) { sendResponse({ success: false, error: error.message }); } } });
如果是在chrome.tabs.onUpdated里触发分析,同样用await等结果出来再给内容脚本发消息:
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { // 只在页面加载完成且是http/https链接时触发 if (changeInfo.status === 'complete' && tab.url.startsWith('http')) { try { const analysisResult = await analyzePageGuest(tabId, changeInfo, tab); chrome.tabs.sendMessage(tabId, { action: 'analysisResult', data: analysisResult }); } catch (error) { chrome.tabs.sendMessage(tabId, { action: 'analysisError', error: error.message }); } } });
两个关键优化提醒
- 别硬编码API密钥:把密钥存在
chrome.storage.local里,用的时候取出来,比如:// 存密钥(可以在扩展设置里做个输入框) chrome.storage.local.set({ vtApiKey: '你的密钥' }); // 取密钥 const { vtApiKey } = await chrome.storage.local.get('vtApiKey'); - 去掉cors-anywhere:Chrome扩展的背景页本身有跨域权限,只要在
manifest.json里加权限就行,不用依赖第三方代理:{ "manifest_version": 3, "name": "钓鱼网站检测器", "version": "1.0", "background": { "service_worker": "background.js" }, "host_permissions": ["https://www.virustotal.com/*"], "permissions": ["tabs", "storage"] }
这样改完,你的异步逻辑就会老老实实等分析完成再响应,再也不会触发那个烦人的runtime.lastError了!
备注:内容来源于stack exchange,提问作者Ale26
相关产品推荐
相关产品推荐

