Chrome扩展中用await异步生成响应,弹窗接收结果为undefined的问题
Chrome扩展消息通信异步响应返回undefined的原因
内容脚本代码
(async () => { function pause(delay) { return new Promise((resolve) => setTimeout(resolve, delay)); } async function myHandler() { await pause(1000); return ['something 1', 'something 2']; } function waitForMessage() { return new Promise((resolve) => { async function onMessageListener(message, sender, sendResponse) { chrome.runtime.onMessage.removeListener(onMessageListener); resolve(true); // 以下硬编码响应可正常被接收! // sendResponse({'results': ['something 1', 'something 2']}); const lines = await myHandler(); const response = {'results': lines}; console.log('Responding', response); // 此处正常,{'results': <字符串数组>} sendResponse(response); // 但弹窗脚本收到的是`undefined`! } chrome.runtime.onMessage.addListener(onMessageListener); }); } waitForMessage(); })();
弹窗脚本代码片段
async function requestFromContentScript() { const message = { type: 'request' }; const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); const tabId = tabs[0].id; return new Promise((resolve) => { chrome.tabs.sendMessage(tabId, message, (result) => { console.log('Got in callback:', result); resolve(result); }); }); }
问题描述
如代码注释所示,硬编码响应时弹窗脚本可正常接收结果,但通过await调用异步函数生成响应时,弹窗脚本收到的结果为undefined,请问这一现象的原因是什么?
原因分析
核心问题出在Chrome扩展消息API的异步处理规则上:
- 当消息监听函数是同步执行时,调用
sendResponse后Chrome会立刻把响应返回给发送方,通道正常关闭。 - 当监听函数包含异步操作(比如用了
async/await),需要延迟调用sendResponse时,必须显式返回true,告知Chrome要保留消息通道,等待异步操作完成后再发送响应。
你的代码中,onMessageListener是async函数,执行到await myHandler()时会暂时让出执行权,此时Chrome会默认认为监听函数已经执行完毕,直接关闭消息通道。后续异步操作完成后再调用sendResponse,此时通道已经关闭,结果无法传递到弹窗,所以弹窗收到undefined。
而硬编码响应的情况是同步调用sendResponse,此时通道还未关闭,所以能正常接收结果。
修复方法
在onMessageListener中,执行异步操作前返回true,让Chrome保留消息通道:
async function onMessageListener(message, sender, sendResponse) { chrome.runtime.onMessage.removeListener(onMessageListener); resolve(true); // 关键:返回true,告知Chrome等待异步响应 return true; const lines = await myHandler(); const response = {'results': lines}; console.log('Responding', response); sendResponse(response); }
内容的提问来源于stack exchange,提问作者AlwaysLearning
相关产品推荐
相关产品推荐

