如何将浏览器扩展Service Worker的错误传递给Content Script?
问题
我开发了一个Manifest V3版本的浏览器扩展,Content Script会向后台Service Worker请求信息。正常流程运行没问题,但部分场景下后台脚本无法获取目标信息,此时我希望后台将包含问题详情的错误传递给Content Script。
然而,当使用sendResponse函数发送Error对象时,Content Script仅收到一个空对象。请问这是什么原因?如何实现从Service Worker向Content Script传递错误?
相关代码
content-script.js
const showResult = (res) => { console.log('Received the following response from background script:\n', res); }; chrome.runtime.sendMessage('send me a user!').then((res) => showResult(res)); chrome.runtime.sendMessage('send me a user!').then((res) => showResult(res));
background-script.js
const responses = [ new Error('something bad happened'), { name: 'John Doe', age: 38 } ]; chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { const response = responses.pop() console.log('Going to send the following response:\n', response); sendResponse(response); });
manifest.json
{ "manifest_version": 3, "name": "A test", "version": "0.0.1", "content_scripts": [ { "matches": ["https://www.google.com/*"], "js": ["content-script.js"] } ], "background": { "type": "module", "service_worker": "background-script.js" } }
控制台输出
后台脚本(background-script.js)输出
Going to send the following response: {name: 'John Doe', age: 38} ------------------------------------------------------- Going to send the following response: Error: something bad happened at background-script.js:2:3
内容脚本(content-script.js)输出
Received the following response from background script: {name: 'John Doe', age: 38} ------------------------------------------------------- Received the following response from background script: {}
浏览器版本:Chromium Version 115.0.5790.170 (Official Build)
原因分析
Chrome扩展的消息传递机制依赖JSON序列化来传输数据,而原生的Error对象的核心属性(如message、stack)默认是不可枚举的。当JSON序列化Error对象时,这些不可枚举的属性会被忽略,最终传递到Content Script的就是一个空对象。
解决方案
不要直接传递Error对象,而是将错误信息转换为普通可枚举对象,在对象中明确标记错误类型并携带必要的错误详情,Content Script接收后再判断处理。
修改后的代码示例
background-script.js
const responses = [ // 将Error转为普通对象,包含错误标记、消息和调用栈 { isError: true, message: 'something bad happened', stack: new Error('something bad happened').stack }, { name: 'John Doe', age: 38 } ]; chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { const response = responses.pop() console.log('Going to send the following response:\n', response); sendResponse(response); });
content-script.js
const showResult = (res) => { // 判断是否为错误响应 if (res.isError) { console.error('Received error from background:', res.message, '\nCall stack:', res.stack); } else { console.log('Received response from background:\n', res); } }; chrome.runtime.sendMessage('send me a user!').then((res) => showResult(res)); chrome.runtime.sendMessage('send me a user!').then((res) => showResult(res));
异步场景适配
如果后台是异步操作(比如请求API)出错,需要在onMessage监听函数中返回true,告知Chrome要等待异步的sendResponse调用:
// background-script.js 异步错误处理示例 chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message === 'send me a user!') { fetch('/api/user-data') .then(res => res.json()) .then(userData => sendResponse(userData)) .catch(err => { // 将捕获的错误转为普通对象发送 sendResponse({ isError: true, message: err.message, stack: err.stack }); }); // 返回true表示异步响应 return true; } });
内容的提问来源于stack exchange,提问作者rnwst
相关产品推荐
相关产品推荐

