Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't constants used for events in Node.js?

I'm new to node, but I come from an extensive background in programming. Everywhere I looked (both in tutorials and in production code I've seen around), people overwhelmingly use hard coded strings instead of constants to identify events.

I picked one random example out of npm's most depended upon packages list to illustrate what I mean: the «request» library — why do they emit and consume the «data» event by typing the string 'data' every time, instead of defining a library-wide constant?

Using constants would be considered good practice in any programming language I'm aware of, and yet node developers seem perfectly content with the hard-coded approach. Why?

like image 564
Bogdan Stăncescu Avatar asked Mar 10 '17 08:03

Bogdan Stăncescu


People also ask

Can I use const in NodeJS?

Const is the variables declared with the keyword const that stores constant values. const declarations are block-scoped i.e. we can access const only within the block where it was declared. const cannot be updated or re-declared i.e. const will be the same within its block and cannot be re-declare or update.

How events are handled in NodeJS?

You can assign event handlers to your own events with the EventEmitter object. In the example below we have created a function that will be executed when a "scream" event is fired. To fire an event, use the emit() method.

Is it better to use const or let?

As a general rule, you should always declare variables with const, if you realize that the value of the variable needs to change, go back and change it to let. Use let when you know that the value of a variable will change. Use const for every other variable.

What is const {} in js?

Constants are block-scoped, much like variables declared using the let keyword. The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be redeclared (i.e. through a variable declaration).


2 Answers

Because it doesn't work for Node.js due to the dynamic nature of JavaScript.

Supposed, a module defined a constant data. Then it would need to export this, as part of its event-emitting API. Something such as:

const data = 'data';

class Api extends EventEmitter () {
  constructor () {
    setTimeout(() => {
      this.emit(data);
    }, 2 * 1000);
  }
}

module.exports = {
  data,
  Api
};

Then, from the outside we would have something such as:

const foo = require('./foo');

const { Api, data } = foo;

const api = new Api();

api.on(data, () => {
  // ...
});

Basically, something like this. Now what if you mistyped data in the beginning? What if instead of

const { Api, data } = foo;

you mistyped:

const { Api, Data } = foo;

It would work, without any error. Data would just be undefined. You don't get an error in JavaScript when you try to access an object's property that does not exist, you just get back undefined.

So, you won't get a compiler error, but now you're emitting (under the hood) 'data', but what you're listening for is undefined. The constant does not help in any way, you still have to make sure that you do not mistype its name.

And that is in no way better or worse than using a string where you are not allowed to mistype anything.

So, to cut a long story short, constants don't improve the situation, they just lead to more typing and make things more complicated - but they don't solve any real problem.

like image 118
Golo Roden Avatar answered Oct 03 '22 21:10

Golo Roden


The short answer is that strings are the best constants available to JavaScript. Hiding them behind some static library variable does not make developers' code any more terse, readable (my opinion), or performant; this is why it never became popular convention to do so.


Fragility

Your question seemed to imply that hard-coded strings are somehow more "fragile" than using variable constants. However, I would argue that this is only true when the "constant" is expected to change over time, and this is hardly the case for any event type because Node.js libraries (and browser APIs, too) strive to maintain some degree of backwards compatibility between releases. Furthermore, the odds that someone would mistype the variable are the same as when using a hard-coded string, because JavaScript has no compile-time checking for property existence or anything else. No guarantees are made either way.


Extra Context

You might have noticed that JavaScript lacks an enum type, which is annoying in a lot of ways.

Older APIs used integer values to fill this void in the language, similar to the way people used to do it in Java. For example, Node#nodeType and XMLHttpRequest#readyState are both designed to be used like so:

var node = document.createTextNode('')

console.log(node.nodeType) //=> 3
console.log(node.nodeType === Node.TEXT_NODE) //=> true

var xhr = new XMLHttpRequest()
console.log(xhr.readyState) //=> 0
console.log(xhr.readyState === XMLHttpRequest.UNSENT) //=> true

This design pattern came to be seen as archaic over time, because people realized (as they did in Java) how little information a number like 4 gives when printed in an error as opposed to the semantic property name UNSENT.

The best available alternative in JS was, and continues to be, string values. Modern APIs like fetch() make use of them quite frequently for passing meaningful configuration options to each method.

The JS community seems to be leaning towards this approach over time, and I think there are some very compelling reasons to do so. However, when you come from a more traditional programming background (especially a familiarity with strongly-typed languages), it might take a little time for you to feel comfortable with this approach. Just keep an open mind and read as many books on the language as you can.

like image 28
gyre Avatar answered Oct 03 '22 21:10

gyre