【问题标题】:Message does not arrive on first page load - Google Chrome Message Passing from Background to Content Script [duplicate]第一页加载时消息未到达 - Google Chrome 消息从背景传递到内容脚本 [重复]
【发布时间】:2014-09-18 23:03:48
【问题描述】:

我正在开发一个谷歌插件/扩展,我遇到了一个问题,我只能推测它的原因。在我的 background.js 后台脚本中,我试图将图像数据发送到我的 content.js 内容脚本。

当我第一次在新标签中加载页面时,我只收到“已发送响应!”,但没有“收到响应”。然后我用 f5 键刷新,这一次我也收到了等待的“收到响应”消息。

有没有可能我的 background.js 根本不在内存中?如果是这样,我该如何解决?当我在 chrome://extensions/ 下重新加载插件并重新加载已经存在的选项卡时,也会发生这种情况。

background.js

chrome.extension.onMessage.addListener(
 function(msg, sender, sendResponse) {
    if((msg.action && (msg.action == "getPixels")) && msg.imgPath)
    {
        var canvas = document.createElement("canvas");
        canvas.style.border = "none";
        var img = new Image();
        img.src = msg.imgPath;
        var thewaitx = function()
        {
            if(img.complete && (img.width + img.height) > 0)
            {
                canvas.width = img.width;
                canvas.height = img.height;
                canvas.getContext("2d").drawImage(img, 0, 0);
                data = canvas.getContext("2d").getImageData(0, 0, img.width, img.height).data

                sendResponse({value: data});
                alert("response sent!");
            }
            else {setTimeout(thewaitx, 2000);}
        };
        thewaitx();

        }
    }
);

content.js

function findDataBySignature()
{
    img = document.getElementsByClassName("someid")[0].getElementsByTagName("img")[0];
    chrome.extension.sendMessage({action: "getPixels", imgPath:img.src}, function(response)
    {
        alert("response received");
        data = response.value;
        //blahblah
    }
}

【问题讨论】:

  • 这就是我迄今为止找到的所有答案的问题。我正在请求我的内容脚本(不是后台脚本!)中的数据。内容脚本运行,在某些时候它说嘿,伙计,后台脚本,这是 url,将图像数据发送给我。后台脚本获取消息并发送答案,但答案永远不会回来。我收到“已发送响应”的事实!是内容脚本已经运行的证明,因为它是唯一可以触发调用的脚本。嗯......现在当我想到这一点时,也必须加载 backg 脚本,因为我收到了“已发送响应!”。很奇怪。
  • 我认为这与旧的内容脚本无关。我知道新代码只在新标签中执行。它通常是我正在更新的内容脚本。但这正是我所知道的。我重新加载扩展,然后我重新加载或打开一个新标签。还是我误解了什么?
  • 啊!那么问题就错了。但是,再次回答。一会儿..
  • 被提名重新开放。原来对同一问题的猜测是错误的。

标签: javascript google-chrome google-chrome-extension background message-passing


【解决方案1】:

很抱歉一开始链接到错误的问题。

在您的代码中,您正在请求一个图像,并且根据它是否已经加载,您要么对其进行处理,要么使用setTimout 等待。

您的代码第二次运行,因为图像已经加载;第一次不是,并且监听器终止而不调用sendResponsesetTimeout 是异步的)。

Google documentation 提到需要特别注意让 Chrome 现在您将异步调用 sendResponse(而不是简单地没有响应):

当事件侦听器返回时,此函数无效,除非您从事件侦听器返回 true 以指示您希望异步发送响应(这将保持消息通道对另一端开放,直到调用 sendResponse)。

因此,要使其正常工作,您需要从您不会立即调用 sendResponse 的分支中发送 return true;


也就是说,我必须评论你的代码:你不应该使用setTimeout 来等待图像加载。使用基于事件的方法:

var img = new Image();
img.onload = function() {
  canvas.width = img.width;
  canvas.height = img.height;
  canvas.getContext("2d").drawImage(img, 0, 0);
  data = canvas.getContext("2d").getImageData(0, 0, img.width, img.height).data

  sendResponse({value: data});
  alert("response sent!");
};
img.src = msg.imgPath;

// Check if image is already loaded (required if from cache)
if(img.complete || img.readyState === 4) { img.onload(); }
else {
  return true; // For asynchronous sendResponse() call
}

【讨论】:

  • 谢谢!有效!由于我是这里的新手,所以我还不能投票,但一旦我达到 15 岁,我就会:)
  • 如果有效,您可以(并且应该)接受答案(分数下的复选标记)
  • 是的,我之前使用过 onload,但是我遇到了你提到的那些缓存问题。很高兴了解 readystate 属性。我的代码中有更多这样的池。也许我现在要消除这种丑陋。
  • 啊...是的,我是这里的新手 ;) 回答已接受 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多