Cara menggunakan nodejs typescript singleton

A singleton is an object which only exists in one copy. Attempting to create an instance will return that single existing one.

Services in Angular are a good example of singletons. But we’re not talking about Angular here.

When do you need a singleton? The answer: when you have a single general purpose service for your entire app. You usually need a singleton if your service needs to retain its state throughout various places in your app.

The essence of singletons

Here’s a very brief example.

export class Logger {  private static instance: Logger;  constructor() {
if (Logger.instance)
return Logger.instance;
Logger.instance = this;
}
log(message) {
console.log(message);
}
}

Now you can use this singleton in your code:

import { Logger } from './services/logger';
const logger = new Logger();
logger.log('This SO goes to the console!');

That’s it. Let’s see a practical example!

The example above makes little practical sense, as we could use console.log(). Let’s modify it a bit. Suppose we want to output the time for every log line. We’d like our server app to output something like this:

2020-11-03
==========
01:23:11 Server listening on port 3000
01:24:33 Incoming request from 89.33.255.23
03:44:05 The cat is hungry
2020-11-04
==========
00:01:01 A new day has just began
01:12:43 The cat is hungry again

So let’s modify our service to do all this. Let’s start with displaying the time for every log line.

log(message) {
const now = new Date();
console.log(``${ now.getHours() }: ${ now.getMinutes() }: ${ now.getSeconds() }` ${message});
}

I’m simplifying the example here and there. The timestamp will not be padded, so you will end up seeing 3:22:1 instead of 03:22:01. I’ll leave that to you to implement.

So now we have timestamps, but we’d like to display the date whenever a new day begins. Let’s add a private variable to our module called lastLogDay. It will store — you guessed it — the last day when a line was displayed.

private lastLogDay = 0;log(message) {
const now = new Date();
if (this.lastLogDay !== now.getDate()) {
console.log(`\n${now.getFullYear()}-${now.getFullMonth()}-{now.getDate()}\n==========\n`);
} console.log(``${ now.getHours() }: ${ now.getMinutes() }: ${ now.getSeconds() }` ${message});
this.lastLogDay = now.getDate();
}

Now before every log output the method checks if the current date is different from the last saved one, and displays the full date if it is. Then after the log output it saves the current date to lastLogDay.

This is why we needed a singleton! If we created a new instance of Logger every time we needed it, all the instances would work, but they’d randomly display the date here and there, whenever either of them notices that the date is different from when they were last called. By having a singleton we have only one Logger, and one lastLogDay.

One of the most popular creational design pattern is the Singleton, which restricts instantiation of a class to a single object only. In this post post, I will show you how to implement the above-mentioned pattern using TypeScript.

TypeScript key features

The bible of the design patterns, namely the book by Gang of Four (GoF), contains code examples in the statically typed C++ language. However, TypeScript allows to implement the Singleton pattern thanks to the following features:

  • support for access modifiers (private, protected, public),
  • support for static methods,
  • being a statically typed language.

The Singleton pattern

Let’s consider the ActionsBus class which is supposed to be instantiated only once, since there should be a single point to dispatch an action. In addition, it should be possible to become notified about each event in the system by simply subscribing in one place:

The key points are:

  • constructor with a private access modifier, which is not accessible outside of the class body,
  • the static instance filed, which is supposed to reference the single instance of the class,
  • the static getInstance method, which is responsible for returning the single instance of the class. In addition, it follows a lazy evaluation strategy, hence it has to create the instance when it’s called for the first time.

Note that within the getInstance method you can reference the class using the this keyword as well:

The Singleton in action

Let’s verify that there’s only a single instance of the ActionsBus class in the system:

First, notice that it’s illegal to instantiate the class directly due to the private access modifier of its constructor. The existence of a single instance has been proved by comparing references to object returned from the invocations of the getInstance static method. In addition, if you subscribe to the action$ observable with the aid of the former reference, you will be notified about the action dispatched using the latter:

Conclusions

The Singleton pattern is one of the easiest to understand, therefore it’s a good starting point to get familiar with the topic. TypeScript (a superset of JavaScript) has all the features required to make use of the design patterns covered in the GoF’s book.