我正在开发一个谷歌插件/扩展程序,我遇到了一个问题,我只能推测它的原因。在我的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
}
}
答案 0 :(得分:1)
很抱歉首先链接到错误的问题。
在您的代码中,您正在申请图片,并且根据图片是否已经加载,您要么对其执行操作,要么使用setTimout
等待。
您的代码第二次运行,因为图像已经加载;第一次不是,并且监听器终止而不调用sendResponse
(setTimeout
是异步的)。
Google documentation提到需要特别注意让Chrome现在以异步方式调用sendResponse
(而不是简单地没有回复):
当事件侦听器返回时,此函数变为无效,除非您从事件侦听器返回true以指示您希望异步发送响应(这将使消息通道保持打开到另一端,直到调用
sendResponse
)。
因此,为了使其有效,您需要return true;
来自您不会立即致电sendResponse
的分支机构。
那就是说,我必须对您的代码发表评论:您不应该使用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
}