111

For example I want to use custom logger:

logger = require('basic-logger'),
logger.setLevel('info')

var customConfig = {
showMillis: true,
showTimestamp: true
}

var log = new logger(customConfig)

How to use this logger in other modules instead of console.log ?

xvatar
  • 3,229
  • 17
  • 20
Bdfy
  • 23,141
  • 55
  • 131
  • 179
  • 2
    see this post http://stackoverflow.com/questions/4140661/global-variables-for-node-js-standard-modules – xvatar Jun 11 '12 at 21:06
  • 1
    Does this answer your question? [Global variables for node.js standard modules?](https://stackoverflow.com/questions/4140661/global-variables-for-node-js-standard-modules) – KyleMit Jan 12 '20 at 04:16
  • 2
    **FYI** Use `global` (lowercase) instead of `GLOBAL` (uppercase) per [node's deprecation warning](https://nodejs.org/api/deprecations.html#deprecations_dep0016_global_root) – KyleMit Jan 12 '20 at 04:17
  • **See Also**: [Node.js global variables](https://stackoverflow.com/q/5447771/1366033) – KyleMit Nov 26 '21 at 20:12

7 Answers7

141

Most people advise against using global variables. If you want the same logger class in different modules you can do this

logger.js

  module.exports = new logger(customConfig);

foobar.js

  var logger = require('./logger');
  logger('barfoo');

If you do want a global variable you can do:

global.logger = new logger(customConfig);
Pickels
  • 33,902
  • 26
  • 118
  • 178
  • 32
    do NOT use global variables! If you start running you application with multiple processes you will get screwed very badly. – TheHippo Jun 11 '12 at 21:17
  • Did you forget a `.` in your global definition? `global.logger = new logger(customConfig);`? – jagill Jul 16 '13 at 21:06
  • 43
    TheHippo, global variables are fine in some cases, even with multiple processes. A logger for example won't have any issues if several process have their own instance of the logger object. – d512 Aug 22 '13 at 20:10
  • use a [Singleton instead (or equivalent)](http://stackoverflow.com/questions/13179109/singleton-pattern-in-nodejs-is-it-needed) of a global to prevent dependency bleed – zamnuts Apr 25 '14 at 02:13
  • 210
    I'm bored to see comments about "do not use globals". In some cases, globals are the unique way to work. I use it commonly to store constant values, like "global.email = 'contact@domain.com'", and use it across my whole project. If tomorrow I want to change it in the whole project, I only need to change it in the app.js (Node example, in this case). I don't know another way to do this in Node than using global. So please, do not categorically say "do not use global variables", just say "be wise using globals". – Eagle May 04 '15 at 09:55
  • 44
    @Eagle I don't really see why you can't import a configuration file that defines your email variable. – Pickels Dec 05 '15 at 15:28
  • 41
    I can, but my complaint is not about if I can use a config file, is about if I can use global vars in a safe way or not. And I can. – Eagle Dec 05 '15 at 23:08
  • 1
    @Pickels required config files are globals too; here's the proof: conf.json: `{"v": "a"}`; lib.js: `var c = require('./conf.json'); console.log("lib: " + c.v); c.v = 'b';`; app.js: `require('./lib'); console.log("app: " + require('./conf.json').v);`. I guess we have to use `fs.readFile` to load the configuration then or deep clone the `require`d object. – TWiStErRob Feb 21 '16 at 10:35
  • Only time I used a global variable was for registering "destroy" method so on process exiting I can call them and cleanly close all threads. – Kulvar Nov 16 '16 at 16:06
  • @eagle `import { email } from ./email` – superluminary Oct 10 '17 at 15:11
  • 1
    I'd just like to point out that pretty much everything built into the language is a global variable (with few notable exceptions: see other answers [(1)](https://stackoverflow.com/questions/46118496/asyncfunction-is-not-defined-yet-mdn-documents-its-usage/49166982#49166982) and [(2)](https://stackoverflow.com/questions/38508420/how-to-know-if-a-function-is-async/49166833#49166833)) but Node-specific stuff is almost (with some exceptions) imported with require, even for builtin stuff like events so using a global in your own code feels more like a language builtin. Most polyfills work that way. – rsp Oct 25 '18 at 12:06
  • And the link to the documentation: https://nodejs.org/dist/latest-v14.x/docs/api/globals.html#globals_global – jehon Nov 26 '20 at 12:30
  • 1
    I agree with Eagle: "Use globals wisely", even if I think the example given is not a good one. I use globals for a custom logger used in dev only (and because I am lazy). – jehon Nov 26 '20 at 12:32
  • can anyone please tell me how I can create a global variable that is accessible, and editable, from all middleware files? i have [a question with more context here](https://stackoverflow.com/questions/70185112/how-to-define-all-socket-io-io-onconnection-logic-outside-of-app-js-in-a-sep) – user1063287 Dec 02 '21 at 05:08
  • Thanks for the advice agfainst globals, I KNOW what I'm doing :D – Benjamin Bouchet May 20 '22 at 18:33
64
global.myNumber; //Delclaration of the global variable - undefined
global.myNumber = 5; //Global variable initialized to value 5. 
var myNumberSquared = global.myNumber * global.myNumber; //Using the global variable. 

Node.js is different from client Side JavaScript when it comes to global variables. Just because you use the word var at the top of your Node.js script does not mean the variable will be accessible by all objects you require such as your 'basic-logger' .

To make something global just put the word global and a dot in front of the variable's name. So if I want company_id to be global I call it global.company_id. But be careful, global.company_id and company_id are the same thing so don't name global variable the same thing as any other variable in any other script - any other script that will be running on your server or any other place within the same code.

Sean H. Worthington
  • 1,701
  • 15
  • 9
  • 1
    It's different because each file/module is implicitly wrapped in an IIFE at build time, so vars are actually local to the IIFE. – superluminary Oct 10 '17 at 15:17
33

you can define it with using global or GLOBAL, nodejs supports both.

for e.g

global.underscore = require("underscore");

or

GLOBAL.underscore = require("underscore");
Shubham Gautam
  • 329
  • 3
  • 7
  • I think this way of using global variable is better than assigning an instance of object to it. This way of using global variables may has no side effects. – AmirHossein Rezaei Jan 14 '21 at 16:48
26

I would suggest everytime when using global check if the variable is already define by simply check

if (!global.logger){
  global.logger = require('my_logger');
}

I've found it to have better performance

Doron Segal
  • 2,242
  • 23
  • 22
  • @wiktus239 It's a check as it doesn't require module to load again - Thus better performance. – suprxd Mar 09 '18 at 05:16
  • 4
    The answer is fine and the `if` can be used to not redefine the global needlessly, but I'd like to point out that `require` doesn't load anything more than once. It loads everything once and caches the result. So the `if` is not required to avoid module parsing and loading, but it is useful to avoid reassigning the value from the cache over and over again. – rsp Oct 25 '18 at 12:00
  • 1
    Or a one-liner: `global.logger ??= require('my_logger');` – Mike May 18 '22 at 23:13
14

Global variables can be used in Node when used wisely.

Declaration of global variables in Node:

a = 10;
GLOBAL.a = 10;
global.a = 10;

All of the above commands the same actions with different syntaxes.

Use global variables when they are not about to be changed

Here an example of something that can happen when using global variables:

// app.js
a = 10; // no var or let or const means global

// users.js
app.get("/users", (req, res, next) => {
   res.send(a); // 10;
});

// permissions.js
app.get("/permissions", (req, res, next) => {
   a = 11; // notice that there is no previous declaration of a in the permissions.js, means we looking for the global instance of a.
   res.send(a); // 11;
});

Explained:

Run users route first and receive 10;

Then run permissions route and receive 11;

Then run again the users route and receive 11 as well instead of 10;

Global variables can be overtaken!

Now think about using express and assignin res object as global.. And you end up with async error become corrupt and server is shuts down.

When to use global vars?

As I said - when var is not about to be changed. Anyways it's more recommended that you will be using the process.env object from the config file.

Raz Buchnik
  • 7,753
  • 14
  • 53
  • 96
7

If your app is written in TypeScript, try

(global as any).logger = // ...

or

Object.assign(global, { logger: // ... })

However, I will do it only when React Native's __DEV__ in testing environment.

Kazuya Gosho
  • 996
  • 13
  • 14
6

May be following is better to avoid the if statement:

global.logger || (global.logger = require('my_logger'));
miltonb
  • 6,905
  • 8
  • 45
  • 55