【问题标题】:Message callback returns a value infrequently - Chrome Extension消息回调不经常返回值 - Chrome 扩展
【发布时间】:2014-10-07 18:09:39
【问题描述】:

我正在构建一个 chrome 扩展,它通过 websockets 与 nodejs 服务器通信。它的重点是使用内容跟踪浏览历史记录。这一切似乎都有效,但偶尔(30% 的时间)传递给 onMessage.addListener 的函数中的回调无法正确触发。让我给你看代码:

background.js

var socket = io('http://localhost:3000/');

var tabLoad = function (tab) {
    socket.emit('page load', tab);
};

var tabUpdate = function (tabid, changeinfo, tab) {
    var url = tab.url;
    if (url !== undefined && changeinfo.status == "complete") {
        tab.user_agent = navigator.userAgent;
        tab.description = '';
        tab.content = '';

        socket.emit('insert', tab);
    }
};

socket.on('inserted', function(page){
    socket.emit('event', 'Requesting page content\n');
    //page = {tab: page, id: docs._id};
    chrome.tabs.sendMessage(page.tab_id, {requested: "content", page: page}, function(data) {
        socket.emit('content', data);
    });

});

try {
    chrome.tabs.onCreated.addListener(tabLoad);
    chrome.tabs.onUpdated.addListener(tabUpdate);
} catch(e) {
    alert('Error in background.js: ' + e.message);
}

内容脚本 - public.js

var messageHandler = function(request, sender, sendContent) {
    if (request.requested == "content") {
        var html = document.getElementsByTagName('html')[0].innerHTML;
        var data = {
            content: html,
            page: request.page
        };
        sendContent(data);
        return true;
    }
};

chrome.extension.onMessage.addListener(messageHandler);

问题是有时 sendContent 中的数据是未定义的,而有时它是可以的。任何想法如何调试这个或我做错了什么?

我尝试将document.getElementsByTagName('html')[0].innerHTML 替换为硬编码的“测试”字符串,但这没有帮助。

youtube/wikipedia 之类的页面似乎永远无法使用,而 facebook/google 则可以使用。

编辑:sendContent 回调在 100% 的情况下会触发,只是传递给它的数据未定义。

编辑:这是清单文件

{
    "manifest_version": 2,

    "name": "Socket test",
    "description": "sockets are cool",
    "version": "1.0",

    "permissions": [
        "http://st-api.localhost/",
        "http://localhost:3000/",
        "tabs",
        "background",
        "history",
        "idle",
        "notifications"
    ],
    "content_scripts": [{
        "matches": ["*://*/"],
        "js": ["public/public.js"]
        //"run_at": "document_start"
    }],
    //"browser_action": {
    //    "default_icon": "logo.png",
    //    "default_popup": "index.html"
    //},
    "background": {
        //"page" : "background.html",
        "scripts": ["socket-io.js", "background.js"],
        "persistent": true
    }
}

【问题讨论】:

  • 尝试删除return true;,在这种情况下你不需要它。
  • 试过了。没有什么不同:(
  • 嗯。在sendMessage 回调中检查chrome.runtime.lastError 的值。我有一种预感,您的内容脚本在需要时不存在。
  • 得到:无法建立连接。接收端不存在。所以你是对的,但这是什么原因造成的,我该如何解决?
  • 马上去试试this

标签: javascript node.js google-chrome-extension websocket


【解决方案1】:

首先,您对sendContent 100% 执行的理解是错误的。

正如在 cmets 中建立的,sendMessage 回调也会在出现错误时执行;在你的情况下,这个错误是"Receiving end does not exist"


错误在于内容脚本的清单声明。 match pattern "*://*/" 将仅匹配 http 和 https URI 上的顶级页面。 IE。 http://example.com/ 会匹配,而http://example.com/test 不会。

最简单的解决方法是"*://*/*",但我建议使用通用匹配模式"<all_urls>"。


修复后,您的代码仍有一些改进。

  • 替换chrome.extension.onMessage(已弃用)并使用chrome.runtime.onMessage
  • 通过检查chrome.runtime.lastError,将sendMessage 部分修改为更具弹性。尽管有广泛的权限,Chrome 仍然不会将任何内容脚本注入某些页面(例如 chrome:// 页面、Chrome 网上应用店)
  • 确保在内容脚本中使用"run_at" : "document_start",以确保在脚本准备好之前不会触发onUpdated 和"complete"。

【讨论】:

  • 太棒了,它有效!我会给你一个额外的 100 代表作为赏金,让你花时间!干杯!
  • 很高兴它有帮助;我不太确定它是否值得额外的赏金,但如果你这样做,我只会“支付”其他答案。
  • 您确实为我节省了大量时间。答案对我的情况很准确,我相信它会在未来对其他人有所帮助:)
  • 在我给你赏金之前,我必须取消选中它作为一个可接受的答案:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-13
  • 2016-03-10
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多