Javascript Express.js子应用程序加载同一模块

Javascript Express.js子应用程序加载同一模块,javascript,node.js,express,Javascript,Node.js,Express,我有一个简单的Express应用程序,可以加载2个子应用程序-登录和发布。子应用程序和顶级应用程序都使用不同的require语句导入一些公共代码,但是当代码运行时,它们看起来共享相同的代码 文件结构为: ├── app.js ├── lib │   ├── Common.js │   ├── login │   │   └── index.js │   └── posts │   └── index.js └── package.json app.js: var express

我有一个简单的Express应用程序,可以加载2个子应用程序-登录和发布。子应用程序和顶级应用程序都使用不同的require语句导入一些公共代码,但是当代码运行时,它们看起来共享相同的代码

文件结构为:

├── app.js
├── lib
│   ├── Common.js
│   ├── login
│   │   └── index.js
│   └── posts
│       └── index.js
└── package.json
app.js:

var
  express  = require( 'express' ),
  Common   = require( './lib/Common' ),
  login    = require( './lib/login' ),
  posts    = require( './lib/posts' ),
  app      = express();

app.use( login );
app.use( posts );
Common.init( "top level" );
app.listen( 3000 );
lib/login/index.js:lib/posts/index.js类似

var
  express = require( 'express' ),
  Common  = require( '../Common' ),
  app     = module.exports = express();

Common.init( "login subapp" );
lib/Common.js:

var stored_text = undefined;

init = function ( text ) {
  console.log( "text: " + text );
  console.log( "before: " + stored_text );
  stored_text = text;
  console.log( "after: " + stored_text );
}

module.exports = {
  init: init
}
当我运行应用程序时,我得到以下输出:

node app.js 
text: login subapp
before: undefined
after: login subapp
text: posts subapp
before: login subapp
after: posts subapp
text: top level
before: posts subapp
after: top level
我希望每个应用程序都有自己的代码副本,所以在此之前:undefined会打印3次。相反,只有要加载的第一个应用程序才会打印此行,下一个要加载的应用程序会从第一个应用程序设置存储的_文本变量


有没有一种方法可以在应用程序之间安全地共享代码?

这种行为——需要缓存和重用的事实,已经有了很好的文档记录,而且非常可取,因为它允许一个应用程序有多个js文件需要“x”,并且所有这些文件都会碰到同一个x,而不必创建其他方法来共享

一般来说,如果我了解您的目标,您可能希望为解决方案采用的方法是将“Common.js”修改为更类似类的结构,并让每个应用程序使用一个新实例。由于某种原因,您已经通过广泛使用的约定选择了将Common大写,只有“构造函数”函数具有初始大写字母,因此它看起来类似

比如:

对于Common.js

// this is a constructor
var Common = function(initStr)
{
   this.storedText = initStr;
}

module.exports = Common;
// this is a constructor
var Common = function(key, initStr)
{
   if(Common.instances[key])
       return Common.instances[key]

   this.storedText = initStr;
   Common.instances[key] = this;
}

Common.instances= {};

module.exports = Common;
在index.js和其他文件中

var Common = require('../Common');

var common = new Common ("instance string");

// code access 'common' from here. 
如果在多个文件中执行此操作,则每个文件都会有自己的公用项,即使所有文件都共享一个公用项(如果愿意的话)

您可以进一步增强这一点,以允许某种类型的键控访问,这样,如果您需要文件A和文件B来共享单个公共实例,您可以使其可用,但我认为上面的内容应该满足您的即时查询

希望这有帮助。如果您需要进一步的澄清,请发表评论,我将密切关注

更新

正如您在评论中所要求的那样,您可以采用以下方法来实现实例的键控共享:

对于Common.js

// this is a constructor
var Common = function(initStr)
{
   this.storedText = initStr;
}

module.exports = Common;
// this is a constructor
var Common = function(key, initStr)
{
   if(Common.instances[key])
       return Common.instances[key]

   this.storedText = initStr;
   Common.instances[key] = this;
}

Common.instances= {};

module.exports = Common;
然后,您可以从不同的文件访问相同的实例,如下所示:

specificButShareable = new Common('postsModule', 'instance data for posts');
请注意,在实现时,如果第二个文件加载了

specificButShareable = new Common('postsModule', 'some other instance data');

返回的公共项仍将具有“POST的实例数据”,而不是“某些其他实例数据”。很明显,如果您愿意,您可以改变这种行为,但以上是该概念的基本版本。

感谢您提供的详细答案,非常有用。我能让你建议的解决方案发挥作用。您能概述一下您提到的共享单实例增强功能吗?这听起来可能是在应用程序之间共享数据的好方法。不客气。我发布了详细解答的更新。Barry感谢这是一个非常酷的东西,我没有想到你可以向函数添加属性,或者你可以将属性作为实例的引用。我仍在努力了解javascript的一些复杂之处。干杯。如果你已经习惯了许多其他语言,那么函数具有属性的想法有点奇怪,但它的好处或功能至少是Javascript的功能性质。我推荐道格拉斯·克罗克福德(Douglas Crockford)的讲座可以在Youtube上找到——他的YUI Conf讲座或《Javascript:The Good Parts》一书都可以作为深入理解Javascript的有用工具。