You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 10:33:15