简体   繁体   中英

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.

But I'd like to create a separate file (game.js) that handles all the game code including socket emissions to certain rooms. However to do that I'll need access to my array with the users/sockets stored in it (which is in 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?

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. For instance, the following module exposes the configuration of a Mongo database.

//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.

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.ts reads user input, and depending on the input, runs functions in 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. 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 .

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.

However, thanks to Edwin's answer, I managed to implement a bridge:

// 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 };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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