后台向前台传消息时无法获取到消息接收方

在background向前台传消息的时候出现报错Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
检查了manifest当中也有声明,content.js和service.js都发现不了错误,究竟是为什么?

manifest代码如下

{    
    "content_scripts": [
      {
        "matches": [
            "<all_urls>"
        ],
        "js": [
            "lib/jquery.min.js",
            "content-scripts/content.js"
        ]
      }
    ]
}

service.js代码如下:

var menuItem = {
    "id": "search_weather",
    "title": "查询天气",
    "contexts": ["all"]
};
chrome.contextMenus.create(menuItem);
chrome.contextMenus.onClicked.addListener(function (clickData) {
    if (clickData.menuItemId == "search_weather") {
        console.log('search_weather')
        
        //天气查询api
        var url = 'http://t.weather.sojson.com/api/weather/city/101030100';
        //使用 Fetch API 发送一个 GET 请求到指定的 url。
        fetch(url)
            //将响应对象转换为文本格式。
            .then(response => response.text())
            //将文本内容解析为 JSON 格式的 JavaScript 对象。
            .then(text => JSON.parse(text))
            //对解析后的 JSON 对象执行的操作,会首先打印JSON对象中,“data”属性的“wendu”值
            .then(result => {
                console.log(result.data.wendu)
                
                chrome.action.setBadgeText({ text: result.data.wendu });
                chrome.action.setBadgeBackgroundColor({ color : [0, 255, 0, 255] });
        
                chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
                    chrome.tabs.sendMessage(tabs[0].id, { todo: "weather", weather_result: result });
                })
                
                //获取设置的提醒温度
                chrome.storage.sync.get("temp", function(wendu){
                    var alert_temp = wendu.temp;
                    console.log("alert_temp="+alert_temp)
                    if (parseFloat(result.data.wendu) >=parseFloat(alert_temp)){
                        var imgurl = chrome.runtime.getURL("icons/logo128.png")
                        chrome.notifications.create("highTempNotify", {
                            type:'basic',
                            iconUrl: imgurl ,
                            title: "高温提示",
                            message: "当前气温较高,请注意防暑",
                        });
                    }
                });
            })
    }
});

content.js代码如下:

chrome.runtime.onMessage.addListener((request,sender,sendResponse) => {
    if(request.todo == "weather"){
        console.log(request)
        //var result = JSON.parse(request)
        $("body").prepend(
            `<div>${request.weather_result.cityInfo.city}今日天气:\
            ${request.weather_result.data.forecast[0].type},\
            ${request.weather_result.data.forecast[0].low},\
            ${request.weather_result.data.forecast[0].high}\
            </div>`
            );    
    }
    
});

从你描述的报错信息 "Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist." 通常是由于在发送消息的时候,接收方没有正确注册监听器(listener)导致的。

在你的代码中,发送消息的代码是在 chrome.tabs.query 回调函数中的:


chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    chrome.tabs.sendMessage(tabs[0].id, { todo: "weather", weather_result: result });
})

这段代码的作用是向当前激活的标签页发送消息 { todo: "weather", weather_result: result }。因此,你需要在标签页中正确注册监听器来接收这个消息。根据你提供的代码,你应该在 content.js 中注册监听器,代码如下:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.todo == "weather") {
        console.log(request.weather_result);
        // TODO: 处理接收到的消息
    }
});

需要注意的是,content.js 中的监听器必须在扩展加载时候就被注册,否则就会出现上述报错信息。可以将监听器代码放在 content_scripts 中的 content.js 文件的顶部,确保在扩展加载时就被注册。

此外,你也需要确保在 manifest.json 中正确声明了需要访问的 URL,例如:

"permissions": [
    "http://*/*",
    "https://*/*"
  ],

这样才能确保扩展可以访问当前标签页并发送消息。