Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/430.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从firefox插件SDK中的内容脚本回调_Javascript_Firefox_Firefox Addon_Firefox Addon Sdk - Fatal编程技术网

Javascript 从firefox插件SDK中的内容脚本回调

Javascript 从firefox插件SDK中的内容脚本回调,javascript,firefox,firefox-addon,firefox-addon-sdk,Javascript,Firefox,Firefox Addon,Firefox Addon Sdk,我正在使用Firefox插件sdk开发一个小扩展,它必须改变页面中DOM元素的内容。我正在使用PageMod添加内容脚本并注册一些事件,其中一些事件我希望通过回调函数传递给它们,如下所示: main.js pageMod.PageMod({ include: "*", contentScriptWhen: 'ready', contentScriptFile: [self.data.url("my_content_script.js")], onAttach: f

我正在使用Firefox插件sdk开发一个小扩展,它必须改变页面中DOM元素的内容。我正在使用
PageMod
添加内容脚本并注册一些事件,其中一些事件我希望通过回调函数传递给它们,如下所示:

main.js

pageMod.PageMod({
    include: "*",
    contentScriptWhen: 'ready',
    contentScriptFile: [self.data.url("my_content_script.js")],
    onAttach: function(worker) {
        worker.port.on("processElement", function(elementSrc, callback) {
            doSomeProcessingViaJsctypes();
            callback("http://someUrl/image.png");
        });
    }
});
var elements = document.getElementsByTagName("img");
var elementsLength = elements.length;
for (var i = 0; i < elementsLength; i++) 
{

    (function(obj) {
        obj.setAttribute("data-processed", "true");
        self.port.emit("processElement", obj.src, function(newSrc) {
            console.log("replaced " + obj.src);
            obj.src = newSrc;
        });
    })(elements[i]);
}
my\u content\u script.js

pageMod.PageMod({
    include: "*",
    contentScriptWhen: 'ready',
    contentScriptFile: [self.data.url("my_content_script.js")],
    onAttach: function(worker) {
        worker.port.on("processElement", function(elementSrc, callback) {
            doSomeProcessingViaJsctypes();
            callback("http://someUrl/image.png");
        });
    }
});
var elements = document.getElementsByTagName("img");
var elementsLength = elements.length;
for (var i = 0; i < elementsLength; i++) 
{

    (function(obj) {
        obj.setAttribute("data-processed", "true");
        self.port.emit("processElement", obj.src, function(newSrc) {
            console.log("replaced " + obj.src);
            obj.src = newSrc;
        });
    })(elements[i]);
}
var elements=document.getElementsByTagName(“img”);
var elementsLength=elements.length;
对于(变量i=0;i
错误

TypeError: callback is not a function
Stack trace:
.onAttach/<@resource://gre/modules/XPIProvider.jsm -> file:///c:/users/sebast~1/appdata/local/temp/tmpjprtpo.mozrunner/extensions/jid1-gWyqTW27PXeXmA@jetpack/bootstrap.js -> resource://gre/modules/commonjs/toolkit/loader.js -> resource://jid1-gwyqtw27pxexma-at-jetpack/testextension/lib/main.js:53
TypeError:回调不是函数
堆栈跟踪:
.Onatach/file:///c:/users/sebast~1/appdata/local/temp/tmpjprtpo.mozrunner/extensions/jid1-gWyqTW27PXeXmA@jetpack/bootstrap.js->resource://gre/modules/commonjs/toolkit/loader.js -> resource://jid1-gwyqtw27pxexma-at-jetpack/testextension/lib/main.js:53
我似乎在网上找不到关于这件事的任何信息。我需要这种方法,因为处理需要一点时间,并且依赖于.dll文件,所以我无法从内容脚本调用它

如果我要处理元素并在调用之后调用
worker.port.emit()
,我必须再次遍历整个树以识别元素并更改其
src
属性。这将花费很长时间,并且会为文档中的每个
img
添加额外的循环

我考虑过生成一个唯一的类名并将其附加到元素的类中,然后调用
getElementsByClassName()
。我没有对此进行测试,但在我看来,这将花费与我上面描述的过程相同的时间

如有任何建议,将不胜感激

编辑:我发现了一个不同的问题。建议使用
windowutils
获取
activeBrowserWindow
,然后对其
内容进行迭代

他还提到

这些低级API不能保证是稳定的,window utils模块甚至没有完整的文档记录


从那以后有什么变化吗?我想知道是否可以使用选项卡获得相同的
content
属性,以及是否可以识别工作人员从哪个选项卡发送
self.port.emit()

当在内容脚本和模块(
main.js
)之间使用消息传递时,只能传递JSON可序列化的数据

传递
应该可以,因为这是一个字符串,因此JSON是可序列化的。
您的代码由于您试图传递的回调函数而中断,因为
函数
不可JSON序列化(与整个DOM节点不可JSON序列化相同)。 另外,
.emit
.on
仅使用第一个参数作为消息负载

在完成处理后,您必须向内容脚本发出另一条消息,而不是回调。由于不能传递DOM元素,所以需要跟踪DOM元素属于哪个消息

好吧,举个例子,我会怎么做。 第一个
main.js

const self = require("sdk/self");
const {PageMod} = require("sdk/page-mod");

function processImage(src) {
  return src + " dummy";
}

PageMod({
  include: "*",
  contentScriptWhen: 'ready',
  contentScriptFile: [self.data.url("content.js")],
  onAttach: function(worker) {
    worker.port.on("processImage", function(data) {
      worker.port.emit("processedImage", {
        job: data.job,
        newSrc: processImage(data.src)
      });
    });
  }
});
在我的设计中,每个
processImage
消息都有一个与之相关联的
job
(请参阅内容脚本),它
main.js
认为是不透明的,只会逐字逐句地发回响应

现在,
data/content.js
,又名。我的内容脚本:

var jobs = new Map();
var jobCounter = 0;

self.port.on("processedImage", function(data) {
  var img = jobs.get(data.job);
  jobs.delete(data.job);
  var newSrc = data.newSrc;
  console.log("supposed replace", img.src, "with", newSrc);
});

for (var i of document.querySelectorAll("img")) {
  var job = jobCounter++; // new job number
  jobs.set(job, i);
  self.port.emit("processImage", {
    job: job,
    src: i.src
  });
}
因此,本质上,对于每个映像,我们将创建一个作业编号(可以是uuid或其他任何东西,但是增加一个计数器对于我们的用例来说已经足够了),并将与该作业编号关联的DOM映像放入一个映射中以跟踪它。 之后,只需将消息发布到
main.js


processedImage
处理程序将接收回作业编号和新源,使用作业编号和
jobs
map返回DOM元素,再次将其从映射中删除(我们不想泄漏它的内容),并执行任何需要的处理;在本例中,只需记录内容。

这是一个非常好且优雅的解决方案。非常感谢你。我已经对它进行了测试,即使使用
jsctypes
后面的处理,它的运行速度也相当快。