Chrome扩展中content-script接收background响应为空问题
问题原因
Chrome扩展的消息传递机制仅支持传递可JSON序列化的数据,ArrayBuffer属于二进制类型,无法直接被序列化,因此直接传递时会被转换为空对象,导致你收到空响应。
解决方案
下面提供两种可行的解决方式,你可以根据需求选择:
方式一:将ArrayBuffer转为Base64字符串传递
这种方式兼容性好,无需担心数据所有权转移问题。
修改background.js
添加数组转Base64的工具函数,将二进制数据转为字符串后发送:
chrome.runtime.onMessage.addListener(cb); function cb(request, sender) { // ArrayBuffer转Base64字符串 function arrayBufferToBase64(buffer) { let binary = ''; const bytes = new Uint8Array(buffer); for (let i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } fetch(`https:${request.imageURL}`) .then(res => res.arrayBuffer()) .then(arrayBuffer => { const base64Data = arrayBufferToBase64(arrayBuffer); chrome.tabs.sendMessage(sender.tab.id, { imageData: base64Data }); }); return true; }
修改content.js
添加Base64转ArrayBuffer的工具函数,接收字符串后还原为二进制数据:
chrome.runtime.sendMessage({ imageURL: 'some-image-url.jpg' }); // Base64字符串转ArrayBuffer function base64ToArrayBuffer(base64) { const binaryString = atob(base64); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; } chrome.runtime.onMessage.addListener(data => { const imageBuffer = base64ToArrayBuffer(data.imageData); console.log(imageBuffer); // 输出正确的ArrayBuffer });
方式二:使用Transferable Objects传递ArrayBuffer
这种方式直接转移二进制数据的所有权,无需转换格式,效率更高,但转移后background端将无法再使用该ArrayBuffer。
修改background.js
发送消息时通过transfer参数传递ArrayBuffer:
chrome.runtime.onMessage.addListener(cb); function cb(request, sender) { fetch(`https:${request.imageURL}`) .then(res => res.arrayBuffer()) .then(arrayBuffer => { // 将ArrayBuffer放入消息体,并指定转移所有权 chrome.tabs.sendMessage( sender.tab.id, { imageBuffer: arrayBuffer }, { transfer: [arrayBuffer] } ); }); return true; }
修改content.js
接收消息时直接获取转移过来的ArrayBuffer:
chrome.runtime.sendMessage({ imageURL: 'some-image-url.jpg' }); chrome.runtime.onMessage.addListener(data => { console.log(data.imageBuffer); // 输出正确的ArrayBuffer });
额外优化:使用sendResponse异步响应
这种方式无需在content.js中单独监听消息,逻辑更简洁:
修改content.js
// Base64转ArrayBuffer工具函数 function base64ToArrayBuffer(base64) { const binaryString = atob(base64); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; } // 发送消息并直接接收响应 chrome.runtime.sendMessage({ imageURL: 'some-image-url.jpg' }, response => { const imageBuffer = base64ToArrayBuffer(response.imageData); console.log(imageBuffer); });
修改background.js
chrome.runtime.onMessage.addListener(cb); function cb(request, sender, sendResponse) { // ArrayBuffer转Base64工具函数 function arrayBufferToBase64(buffer) { let binary = ''; const bytes = new Uint8Array(buffer); for (let i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } fetch(`https:${request.imageURL}`) .then(res => res.arrayBuffer()) .then(arrayBuffer => { const base64Data = arrayBufferToBase64(arrayBuffer); sendResponse({ imageData: base64Data }); }); return true; // 必须返回true,告知Chrome等待异步响应 }
内容的提问来源于stack exchange,提问作者Jefter Rocha
相关产品推荐
相关产品推荐

