给出以下模块:
module.exports = function() {
var env;
var module = {};
module.setEnv= function(myEnv) {
env = myEnv; // env may be set to a different value per user
}
module.doActionWithEnv = function() {
...
}
...
return module;
}
我需要这样的模块:
var myModule = require('/myModule')();
现在我的问题是,我的模块是否在访问该网站的两个不同用户之间共享?我的意思是,如果一个用户设置私有env变量,然后另一个调用依赖于env的模块内的某个函数,从而得到错误的结果,就会发生冲突吗?
感谢。
答案 0 :(得分:5)
服务器上的变量通常是每个服务器进程一次,而不是每个用户发出一次请求。传递给请求处理程序的req
和res
对象等变量是为每个请求唯一创建的。每个用户变量通常需要某种会话管理层,以允许服务器识别正在发出请求的用户,然后访问为该特定用户存储的数据。您可以阅读Express Sessions或Node.js and Express Sessions或Express.js Sessions – A Detailed Tutorial,了解有关在Express中使用会话的详细信息,并且有许多NPM模块可用于实现与Express的会话,但express-session
可能是最受欢迎。
要解释您的代码,请在代码的这一行:
var myModule = require('/myModule')();
每次拨打电话都会收到一个新的myModule
。因此,每次调用该模块构造函数时,都会得到一个新的myModule
对象,其中包含一个新的env
。
但是,如果您只调用一次构造函数并且代码中只有一个myModule
变量,而代表不同用户的Web服务器的多个请求都使用相同的myModule变量,则它们都将是共享相同的myModule
对象,因此在其中共享相同的env
变量。
使您的情况有点混乱的原因是当您执行require('/myModule')
时创建的node.js中的模块在node.js中被缓存和共享。因此,就node.js系统而言,只有一个实际的myModule.js
加载模块。但是,每次调用模块构造函数时,您自己的代码都会创建一个新对象(您还将其命名为module
,这会让事情变得混乱)。因此,如果您调用构造函数5
次,例如:
var m = require('/myModule');
var x1 = m();
var x2 = m();
var x3 = m();
var x4 = m();
var x5 = m();
甚至:
var x1 = require('/myModule')();
var x2 = require('/myModule')();
var x3 = require('/myModule')();
var x4 = require('/myModule')();
var x5 = require('/myModule')();
然后,变量x1
到x5
中将有5个单独的对象,每个对象都有自己的env
变量。
但是,如果你这样做一次:
var myObj = require('/myModule')();
myObj.setEnv("hello");
然后,多个请求处理程序都引用了myObj
这样的对象:
app.get('/request1', function(req, res) {
myObj.setEnv("goodbye");
}};
app.get('/request2', function(req, res) {
myObj.setEnv("adios");
}};
然后,无论用户发起请求,这两个请求处理程序都将在同一个myObj
对象上运行。
那我怎么能避免这个问题?
如果您希望存储在服务器上的每用户信息,则通常使用sessions
。虽然有很多方法可以实现会话,但他们通常会在每个用户首次访问您的网站时为每个用户设置一个唯一的Cookie。然后,服务器上有一个存储机制,可以访问属于具有该cookie值的用户的数据。您不能使用普通的JS变量来存储每个用户的状态。您通常会使用对象查找(通过cookie ID)或某种类型的数据库。
由于看起来您正在使用Express,因此有几个NPM模块将挂钩到Express并为您实现会话。 Express最受欢迎的会话实现是快速会话。