Javascript 使用前初始化RequireJS模块

Javascript 使用前初始化RequireJS模块,javascript,dependency-injection,module,initialization,requirejs,Javascript,Dependency Injection,Module,Initialization,Requirejs,假设我有三个模块和一个主模块,如下所示: //Module A define([''], function(){ function initialize(param1, param2){ //initialize stuff } //other stuff return { initialize: initialize, //whatever else }; }); //Module B define(['ModuleA'],

假设我有三个模块和一个主模块,如下所示:

//Module A
define([''], function(){
   function initialize(param1, param2){
      //initialize stuff
   }
   //other stuff

   return {
      initialize: initialize,
      //whatever else
   };
});

//Module B
define(['ModuleA'], function(ModuleA){
   function initialize(param2, param3){
      //initialize stuff using ModuleA
   }
   //other stuff

   return {
      initialize: initialize,
      //whatever else
   };
});

//Module C
define(['ModuleB'], function(ModuleB){
   function initialize(param4, param5){
      //initialize stuff using ModuleB
   }
   //other stuff

   return {
      initialize: initialize,
      //whatever else
   };
});

//main module
require(['ModuleA', 'ModuleB', 'ModuleC'], function(ModuleA, ModuleB, ModuleC){
   ModuleA.initialize(arg1, arg2);
   ModuleB.initialize(arg3, arg4);
   ModuleC.initialize(arg5, arg6);
});

这里的问题是主模块中的所有初始化调用之间存在时间耦合。一、 作为程序员,必须记住模块初始化的顺序。如果ModuleB在ModuleA之前初始化,那么它基本上将使用未初始化的模块,因为ModuleA尚未初始化。现在,我可以使用依赖项注入,实际上我通过initialize方法中的参数传递ModuleB和ModuleC它们的依赖项,但这会破坏requirejs处理依赖项的目的。我最好只使用脚本标记并手动传递依赖项,确保每个脚本都是独立的。我很想知道是否还有其他的解决办法。谢谢

您可以在define函数中进行模块初始化,并在
define([..]
中指定其依赖项:

//Module A
define(['SomeModule'], function(SomeModule){
  // initialization of the module

  return {
    //initializedModuleInterface..
  };
});
如果您在模块之间遇到循环依赖,那么您可以在从模块返回的界面中,通过在
定义([..]
中不要求第二个模块,而是在模块本身被使用时:
require(“a”)来解除第二个模块的需要,直到使用模块提供的功能为止.doSomething();

初始化参数本身可以是提供配置参数的另一个模块


编辑1:添加requirejs作为动态模块定义器和加载程序的用法

如果需要动态依赖注入机制的结构,您仍然可以使用requirejs。但不确定它是否是为它设计的:

1.当您手头有必要的配置变量时,通过requirejs执行动态模块定义

例如:

angular.module('myModule')
.run(function () {
  define('myConf', [], function() {
    return {
      confA: 1,
      confB: 2
    };
  });
});
2.在依赖于
myConf
模块的模块中,请照常执行:

// Module: ModuleA
define(['myConf', function(myConf) {
  // initialization with myConf values.
  console.log(myConf.confA);

  return some_interface;
});
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
  // doSomething with moduleA
});
// confModule
define([], function () {
   var resolveMain;
   var rejectMain;

   var promise = new Promise(resolve, reject) {
       resolveMain = resolve;
       rejectMain = reject;
   }

   return {
       init: function (confVarA, confVarB) {
           try {
             var moduleInitialized = {
               // some preparation of confModule
               confVarA: confVarA,
               confVarB: confVarB
             };
             resolve(moduleInitialized);
           } 
           catch (e) {
              rejectMain(e);
           } 
       },

       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
// moduleA
define(['confModule'], function (confModule) {
   var resolveMain;
   var rejectMain;

   var promise = confModule.then(function(confModuleData) {
      var moduleBInterface = {
        // prepare module b 
      };

      return moduleBInterface; // this make the promise return another promise to wait on for moduleBInterface return;
   };

   return {
       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
define(['confModule', function (confModule) {
   // some async get of confData
   $.get(url, function (data) {
     confModule.init(data.a, data.b);
   });
});
define(['moduleA'], fucntion (moduleA) {
  moduleA.then(function (moduleAInteface) {
    // do something with moduleA.
  });
});

3.在应用程序的生命周期中,当需要
ModuleA
ModuleB
。则:

// Module: ModuleA
define(['myConf', function(myConf) {
  // initialization with myConf values.
  console.log(myConf.confA);

  return some_interface;
});
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
  // doSomething with moduleA
});
// confModule
define([], function () {
   var resolveMain;
   var rejectMain;

   var promise = new Promise(resolve, reject) {
       resolveMain = resolve;
       rejectMain = reject;
   }

   return {
       init: function (confVarA, confVarB) {
           try {
             var moduleInitialized = {
               // some preparation of confModule
               confVarA: confVarA,
               confVarB: confVarB
             };
             resolve(moduleInitialized);
           } 
           catch (e) {
              rejectMain(e);
           } 
       },

       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
// moduleA
define(['confModule'], function (confModule) {
   var resolveMain;
   var rejectMain;

   var promise = confModule.then(function(confModuleData) {
      var moduleBInterface = {
        // prepare module b 
      };

      return moduleBInterface; // this make the promise return another promise to wait on for moduleBInterface return;
   };

   return {
       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
define(['confModule', function (confModule) {
   // some async get of confData
   $.get(url, function (data) {
     confModule.init(data.a, data.b);
   });
});
define(['moduleA'], fucntion (moduleA) {
  moduleA.then(function (moduleAInteface) {
    // do something with moduleA.
  });
});
这里的诀窍是via
define('myConf',[],function(){..})
。它允许您在应用程序生命周期内的任何时候动态地定义模块,而无需文件。据我所知,它主要用于requirejs捆绑解决方案


编辑2:第二种方法-使用requirejs模块内的承诺作为内部依赖关系管理。

另一种可以使用的方法是在requirejs模块内部使用来指定要等待的依赖项

我们可以将模块主结构定义为承诺,并在获得必要数据时通过接口init函数解析它

1.我们通常将每个模块指定为系统中的文件。 2.在
confModule
中,我们希望动态初始化,我们按照以下模式构建它:

// Module: ModuleA
define(['myConf', function(myConf) {
  // initialization with myConf values.
  console.log(myConf.confA);

  return some_interface;
});
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
  // doSomething with moduleA
});
// confModule
define([], function () {
   var resolveMain;
   var rejectMain;

   var promise = new Promise(resolve, reject) {
       resolveMain = resolve;
       rejectMain = reject;
   }

   return {
       init: function (confVarA, confVarB) {
           try {
             var moduleInitialized = {
               // some preparation of confModule
               confVarA: confVarA,
               confVarB: confVarB
             };
             resolve(moduleInitialized);
           } 
           catch (e) {
              rejectMain(e);
           } 
       },

       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
// moduleA
define(['confModule'], function (confModule) {
   var resolveMain;
   var rejectMain;

   var promise = confModule.then(function(confModuleData) {
      var moduleBInterface = {
        // prepare module b 
      };

      return moduleBInterface; // this make the promise return another promise to wait on for moduleBInterface return;
   };

   return {
       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
define(['confModule', function (confModule) {
   // some async get of confData
   $.get(url, function (data) {
     confModule.init(data.a, data.b);
   });
});
define(['moduleA'], fucntion (moduleA) {
  moduleA.then(function (moduleAInteface) {
    // do something with moduleA.
  });
});
我们解决了这个承诺。附加链接提供了更多关于这种模式的优点和缺点的信息

3.在依赖模块中,我们以相同的模式定义它们,而不需要init功能,并且添加了等待confModule的承诺:

// Module: ModuleA
define(['myConf', function(myConf) {
  // initialization with myConf values.
  console.log(myConf.confA);

  return some_interface;
});
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
  // doSomething with moduleA
});
// confModule
define([], function () {
   var resolveMain;
   var rejectMain;

   var promise = new Promise(resolve, reject) {
       resolveMain = resolve;
       rejectMain = reject;
   }

   return {
       init: function (confVarA, confVarB) {
           try {
             var moduleInitialized = {
               // some preparation of confModule
               confVarA: confVarA,
               confVarB: confVarB
             };
             resolve(moduleInitialized);
           } 
           catch (e) {
              rejectMain(e);
           } 
       },

       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
// moduleA
define(['confModule'], function (confModule) {
   var resolveMain;
   var rejectMain;

   var promise = confModule.then(function(confModuleData) {
      var moduleBInterface = {
        // prepare module b 
      };

      return moduleBInterface; // this make the promise return another promise to wait on for moduleBInterface return;
   };

   return {
       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
define(['confModule', function (confModule) {
   // some async get of confData
   $.get(url, function (data) {
     confModule.init(data.a, data.b);
   });
});
define(['moduleA'], fucntion (moduleA) {
  moduleA.then(function (moduleAInteface) {
    // do something with moduleA.
  });
});
4.在我们的代码中,我们可以在获得所需数据时初始化confModule:

// Module: ModuleA
define(['myConf', function(myConf) {
  // initialization with myConf values.
  console.log(myConf.confA);

  return some_interface;
});
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
  // doSomething with moduleA
});
// confModule
define([], function () {
   var resolveMain;
   var rejectMain;

   var promise = new Promise(resolve, reject) {
       resolveMain = resolve;
       rejectMain = reject;
   }

   return {
       init: function (confVarA, confVarB) {
           try {
             var moduleInitialized = {
               // some preparation of confModule
               confVarA: confVarA,
               confVarB: confVarB
             };
             resolve(moduleInitialized);
           } 
           catch (e) {
              rejectMain(e);
           } 
       },

       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
// moduleA
define(['confModule'], function (confModule) {
   var resolveMain;
   var rejectMain;

   var promise = confModule.then(function(confModuleData) {
      var moduleBInterface = {
        // prepare module b 
      };

      return moduleBInterface; // this make the promise return another promise to wait on for moduleBInterface return;
   };

   return {
       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
define(['confModule', function (confModule) {
   // some async get of confData
   $.get(url, function (data) {
     confModule.init(data.a, data.b);
   });
});
define(['moduleA'], fucntion (moduleA) {
  moduleA.then(function (moduleAInteface) {
    // do something with moduleA.
  });
});
5.在我们的代码中,当使用moduleA时,我们需要使用它作为承诺:

// Module: ModuleA
define(['myConf', function(myConf) {
  // initialization with myConf values.
  console.log(myConf.confA);

  return some_interface;
});
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
  // doSomething with moduleA
});
// confModule
define([], function () {
   var resolveMain;
   var rejectMain;

   var promise = new Promise(resolve, reject) {
       resolveMain = resolve;
       rejectMain = reject;
   }

   return {
       init: function (confVarA, confVarB) {
           try {
             var moduleInitialized = {
               // some preparation of confModule
               confVarA: confVarA,
               confVarB: confVarB
             };
             resolve(moduleInitialized);
           } 
           catch (e) {
              rejectMain(e);
           } 
       },

       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
// moduleA
define(['confModule'], function (confModule) {
   var resolveMain;
   var rejectMain;

   var promise = confModule.then(function(confModuleData) {
      var moduleBInterface = {
        // prepare module b 
      };

      return moduleBInterface; // this make the promise return another promise to wait on for moduleBInterface return;
   };

   return {
       then: function (successFn, errorFn) {
          return promise.then(successFn, errorFn);
       } 
   }
});
define(['confModule', function (confModule) {
   // some async get of confData
   $.get(url, function (data) {
     confModule.init(data.a, data.b);
   });
});
define(['moduleA'], fucntion (moduleA) {
  moduleA.then(function (moduleAInteface) {
    // do something with moduleA.
  });
});

实际上我已经考虑过了,但是我需要初始化函数,因为我需要传入参数(在本例中是从主模块传入的)。如果我以这种方式进行初始化,那么我将无法传递任何信息。不过,感谢您的输入!我认为您正在尝试使用requirejs作为一种通用依赖项注入机制,手头有一个注入器。我已更新了我的答案。但不确定它是否用于此用途:)但将数据从主模块传递到其他模块以初始化它们似乎是一个常见的问题。为什么RequireJS不适用于此,那么这么多大型软件项目是如何使用它的?有没有其他我不知道的结构化程序的方法?关于您的编辑,您是否在“步骤1”中使用angular?1.Angular只是我在应用程序生命周期的某个时候初始化主配置模块的一个例子,而不是在我检查过的种子测试项目的开始阶段。你也可以在jquery文档就绪或ajax调用之后进行初始化。2.
not designed
只是我的解释。只是在我之前的测试中没有看到这种用法项目。但这同样是一个干净有效的解决方案。3.这是一个常见问题。您主要通过使用模块框架和依赖注入机制(例如Angular)来解决它。但他们实际上在做同样的设计模式。在代码中指定依赖项并等待它们。