Javascript代码模块相互导入[Firefox插件]

时间:2014-02-11 23:11:26

标签: javascript firefox firefox-addon xpcom jsm

我在使用javascript代码模块进行firefox插件时遇到了这种奇怪的行为。我不确定这是一个错误还是一个糟糕的设计进行相互导入。

所以我们假设有3个模块a,b和c。

a.js

var EXPORTED_SYMBOLS = ["a"];                                                       
Components.utils.import("resource://mymodule/c.js");                                 
Components.utils.import("resource://mymodule/b.js");                                 

var a = {                                                                           
    init: function() {                                                              
        dump("A init\n");                                                           
        b.init();                                                                   
    }                                                                               
};     

b.js

var EXPORTED_SYMBOLS = ["b"];
Components.utils.import("resource://mymodule/c.js");

var b = {
    init : function() {
        try {
            dump("B init\n");
            dump(c.foo() + "\n");
        } catch (e) {
            dump("Error C init : " + e.message + "\n");
        }
    }
};

c.js

var EXPORTED_SYMBOLS = ["c"];
Components.utils.import("resource://mymodule/b.js");

var c = {
    foo : function() {
        return "C Foo";
    },
};

a.init()在外部调用。现在使用上面的代码,我从b中找到了未定义的'c'。

A init
B init
Error C init : c is undefined

经过一些故障排除后,我意识到要纠正这个问题,

  • 我可以在a.js内交换导入(b在c之前导入)
  • 或者我可以删除相互导入(从c中删除b的导入) 无论如何,事情都没有问题。

在我的实际代码中,b和c表示一些与UI相关的东西,它们具有相互依赖性。我可以完全摆脱相互导入的模块,并为其中一个注册回调函数。但我想知道导致这种行为的原因。据我所知the documentation没有任何严格的模块导入指南。由于模块的缓存,我也知道one module when imported multiple times will be shared。但不知何故无法解释这一点。我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

我有一个关于发生了什么的理论,虽然我没有尝试在调试器中运行代码来确保:

  • a.js运行并导入c.js
  • c.js运行并导入b.js(定义{{​​1}}之前!)
  • b.js运行并导入c.js.但是c.js再次运行,因为它之前已经导入过一次。
  • 由于c在c.js范围内仍未定义(因为c尚未继续运行;它仍在等待第2行的c.js调用返回), import被注入b.js范围。
  • b.js完成执行。
  • c.js完成执行。
  • a.js完成执行。

因此b.js永远不会收到c = undefined的有效绑定,而c在尝试访问b.init()时会抛出异常。

如果这个理论是正确的,我认为你可以通过将b.js和c.js中的导入调用移到这些文件的底部来修复错误。