简体   繁体   English

跨 Node.js 模块共享变量的更好做法是什么

[英]What is the better practice for sharing variables across Node.js modules

So I'm writing a multiplayer game with Socket.io and most of the socket calls are handled in the main file (app.js) including storing usernames and the sockets they're connected to.因此,我正在使用 Socket.io 编写多人游戏,并且大部分套接字调用都在主文件 (app.js) 中处理,包括存储用户名和它们所连接的套接字。

But I'd like to create a separate file (game.js) that handles all the game code including socket emissions to certain rooms.但我想创建一个单独的文件 (game.js) 来处理所有游戏代码,包括特定房间的套接字排放。 However to do that I'll need access to my array with the users/sockets stored in it (which is in app.js)但是,要做到这一点,我需要使用存储在其中的用户/套接字(在 app.js 中)访问我的数组

So I'm wondering what the best way to share the variable would be?所以我想知道共享变量的最佳方式是什么? Should I pass the the array reference through every function that I need it in?我应该通过我需要它的每个函数传递数组引用吗? Or should I write a function that is called once and creates a global variable (or the scope that I need it in) with a reference to the array?或者我应该编写一个调用一次的函数并创建一个全局变量(或我需要它的范围)并引用数组?

Also If I should ever need to share the same dependency across multiple files should I call require in each one of them?另外,如果我需要在多个文件之间共享相同的依赖项,我应该在每个文件中调用 require 吗?

About Modules and the use Global/Shared State关于模块和使用全局/共享状态

An interesting aspect of modules is the way they are evaluated.模块的一个有趣方面是它们的评估方式。 The module is evaluated the first time it is required and then it is cached.该模块在第一次需要时被评估,然后被缓存。 This means that after it has been evaluated no matter how many times we require it, we will always get the same exported object back.这意味着无论我们需要多少次,在对它进行评估之后,我们总是会得到相同的导出对象。

This means that, although Node provides a global object, it is probably better to use modules to store shared stated instead of putting it directly into the global object.这意味着,虽然 Node 提供了一个global对象,但最好使用模块来存储共享语句,而不是直接将其放入全局对象中。 For instance, the following module exposes the configuration of a Mongo database.例如,以下模块公开了 Mongo 数据库的配置。

//module config.js

dbConfig = {
  url:'mongodb://foo',
  user: 'anakin',
  password: '*******'
}

module.exports = dbConfig;

We can easily share this module with as many other modules as we want, and everyone of them will get the exact same instance of the configuration object since the module is evaluated only once and the exported object is cached from there on.我们可以轻松地与任意数量的其他模块共享此模块,并且每个模块都将获得完全相同的配置对象实例,因为该模块仅被评估一次,并且导出的对象从那里开始缓存。

//foo.js
var dbConfig1 = require('./config');
var dbConfig2 = require('./config');
var assert = require('assert');
assert(dbConfig1==dbConfi2);

So, for your specific problem, the shared state that you want to share can reside in a singleton object exposed by whatever module you have.因此,对于您的特定问题,您想要共享的共享状态可以驻留在由您拥有的任何模块公开的单例对象中。 Just make sure your singleton object is the one being exposed in your module and you will always get a reference back to it every time you require it.只要确保您的单例对象是在您的模块中公开的对象,并且每次您需要它时,您总是会得到对它的引用。

如果“变量”是指对套接字的引用 - 您可能需要考虑将回调或模块传递给处理发射的 game.js - 但该 game.js 在必要时调用。

Like Edwin Dalorzo mentioned, having a separate file for all your variables seems the best.就像 Edwin Dalorzo 提到的那样,为所有变量创建一个单独的文件似乎是最好的。

I've had a similar problem for a few hours now because I didn't know that variables were persistent.几个小时以来,我遇到了类似的问题,因为我不知道变量是持久的。 The scenario that I had was:我的场景是:

I have two files cli.ts and main-lib.ts .我有两个文件cli.tsmain-lib.ts cli.ts reads user input, and depending on the input, runs functions in main-lib.ts . cli.ts读取用户输入,并根据输入运行main-lib.ts函数。 While main-lib.ts is busy validating the input, cli.ts uses some global variables that main-lib.ts generates when a test passes.main-lib.ts忙于验证输入时, cli.ts使用main-lib.ts在测试通过时生成的一些全局变量。 The only limitation is that I can't mix the main-lib.ts code with the cli.ts , I can only share the function callValidateFunction .唯一的限制是我不能将main-lib.ts代码与cli.ts ,我只能共享函数callValidateFunction

The issue that I had originally thought of was: if I were to make a global-vars.ts file, the variables' data will still be different for each call of require (ie, calling setVar(...) will only change the variable value that was imported.我最初想到的问题是:如果我要制作一个global-vars.ts文件,每次调用require变量的数据仍然不同(即调用setVar(...)只会改变导入的变量值。

However, thanks to Edwin's answer, I managed to implement a bridge:但是,感谢 Edwin 的回答,我设法实现了一个桥梁:

// cli.ts

import { setVar, getVar } from "./var-bridge";
import { callValidateFunction } from "./main-lib";

function run(args: string[]): void {
    // ...
    if (arg == "--email") {
        // Set the test status.
        setVar("testStatus", "pending");
        
        // Validate the input email address.
        callValidateFunction("validateEmail", nextArg());
        
        // Get the testStatus.
        const testStatus: string = getVar("testStatus");
    }
    // ...
}
// main-lib.ts

import { setVar, getVar } from "./var-bridge";

const funcs: {name: string, func: (arg: string) => boolean} = {};

funcs.validateEmail = function(arg: string): boolean {
    let passed: boolean = false;
    // ...
    return passed;
};

function callValidateFunction(functionName: string, arg: string): void {
    // ...
    const passed = funcs[functionName](arg);
    if (passed) setVar("testStatus", "passed");
}

// ...
// var-bridge.ts

const variables: {name: string, value: any} = {
    "testStatus": "",
    // ...
};

function setVar(varName: string, varValue: any): void {
    variables[varName] = varValue;
}

function getVar(varName: string): any {
    return variables[varName];
}

export { setVar, getVar };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM