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

时间:2017-11-02 03:11:36

标签: javascript google-chrome google-chrome-extension

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

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

popup js

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

背景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;
});

内容脚本

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;
});

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

1 个答案:

答案 0 :(得分:8)

@wOxxO谢谢,你是对的。

我使用Promise样式重写代码,现在可以正常工作。

我这样重写的代码。

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;
});

我可以直接从popup发送消息到contentcript。