Javascript 获取“无法建立连接。接收端不存在。” 当内容脚本 sendResponse 到后台时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47066984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:43:17  来源:igfitidea点击:

Getting "Could not establish connection. Receiving end does not exist." when content script sendResponse to background

javascriptgoogle-chromegoogle-chrome-extension

提问by Donghua Liu

I wrote a chrome extension, popup js will send a message to background and background will redirect the message to content script, after some network request, the result should be returned to the background and then popup js.

我写了一个chrome扩展,popup js会向后台发送消息,后台将消息重定向到内容脚本,经过一些网络请求,结果应该返回到后台然后popup js。

Below are some simplified pieces of my code.

下面是我的代码的一些简化部分。

popup js

弹出js

$('.porintButton').click(function() {
    switch (this.id) {
        case 'learningPointButton':
            chrome.runtime.sendMessage({ action: 'learning' }, callback);
            processResult();
            break;
    }
    return true;
});

backgound js

后台js

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.tabs.sendMessage(tabs[0].id, request, response => {
            if (chrome.runtime.lastError) {
                // If I click learningPointButton, the line will excute, and log 'ERROR:  {message: "Could not establish connection. Receiving end does not exist."}' 
                console.log('ERROR: ', chrome.runtime.lastError);
            } else {
                console.log('The Content Script got the following Message: ' + JSON.stringify(response));
                sendResponse(response);
            }
        });
    });
    return true;
});

content script

内容脚本

chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
    console.info('contentscript', request, sender);
    switch (request.action) {
        case 'learning':
            // this simulate network async request, will not work, 
            setTimeout(() => {
                sendResponse({ action: request.action, result: 'ok' });
            }, 0);
            // this works
            // sendResponse({ action: request.action, result: 'ok' });
            break;
    }
    // I have read https://developer.chrome.com/extensions/messaging#simple and return true here
    return true;
});

If I change the message tunnel to the Long-lived connections, it will work, why?

如果我将消息隧道更改为 Long-lived connections,它将起作用,为什么?

采纳答案by Donghua Liu

@wOxxO Thanks, you are right.

@wOxxO 谢谢,你说得对。

I rewrite the code using Promise style, and it works now.

我使用 Promise 风格重写了代码,现在它可以工作了。

my rewritten code like this.

我这样重写的代码。

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.info('contentscript', request, sender);
    switch (request.action) {
        case 'learning':
            Promise.all([doLearning(), doLearning(), doLearning()])
                .then(unusedData => {
                    return getScore();
                })
                .then(scores => {
                    console.info(scores);
                    sendResponse({ action: request.action, result: 'ok', scores: scores });
                })
                .catch(e => {
                    console.error(e);
                    sendResponse({ action: request.action, result: 'error', message: e });
                });
            break;
        case 'score':
            getScore().then(scores => {
                console.info(scores);
                sendResponse({ action: request.action, result: 'ok', scores: scores });
            }).catch(e => {
                console.error(e);
                sendResponse({ action: request.action, result: 'error', message: e });
            });
            break;
    }
    return true;
});

And I can send message from popup to contentscript directly.

我可以直接将消息从弹出窗口发送到 contentscript。