How To Single Instance Service Node Js
Today I volition be introducing and using the Singleton Design Blueprint, using Node.js (with typescript) and Express library.
First, Why would I need Singelton?
Sometimes you need to make certain that you have one and only one example of an object. This is where the singleton pattern can exist useful. A singleton represents a single instance of an object. Only one can be created, no matter how many times the object is instantiated. If there's already an instance, the singleton will create a new one.
Let's take a look at some use cases that would exist nice to exist
Information technology is popular to utilise a database connection (like MongoDB) within a Node.js application. Just where and how you should instantiate that connectedness?
There are several ways to do it. You lot could just create a file dedicated for this connection that handles the connectedness for the database.
It is popular to use logger library such equally Winston. Where should you instantiate the logger and define it?
Again - you could create a dedicated file to handle this whole affair.
There are more use cases of grade, depends on your application. Merely we can already see - we have 2 dedicated files to manage. What if it would abound? What if you desire to have some logic with each? And then in my opinion the whole thing becomes complicated and makes your code dirty.
An optional solution
Utilize a primal singleton class for these global stuff to manage it in one place, well-organized.
So we are going to create simple server that connects to MongoDB and logs some text to the console & external file. For this I'm gonna exist using Typescript, because information technology makes the creation of the singleton class more than easy, and besides that, why non?
For this, let's create a file with arbitrary name: server-global.ts
. So we know we volition exist using MongoDB and logging text. So let's install via npm
the three packages: mongoose
, @types/mongoose
, winstion
: npm i mongoose winston
, npm i -D @types/winston
.
So let'due south first build a simple grade ServerGlobal
inside the file we created:
import mongoose from ' mongoose ' ; import winston from ' winston ' ; class ServerGlobal { } export default ServerGlobal ;
So what makes a course singleton? We should avoid creating more than ane instance of the form somehow. Making the form constructor to individual one would easily solve it - then you lot would not be able to instantiate the form at all exterior the class.
The problem is.. how the singleton instance is being created?
So making the constructor private, does not hateful yous cannot instantiate the class within the class:
import mongoose from ' mongoose ' ; import winston from ' winston ' ; class ServerGlobal { individual static _instance : ServerGlobal ; private constructor () { } static getInstance () { if ( this . _instance ) { return this . _instance ; } this . _instance = new ServerGlobal (); return this . _instance ; } } export default ServerGlobal ;
And so what happened here?
We manage the singleton instance within the class. Then we provide function, getInstance
, to allow using the singleton outside the class. Both are static ones, because as I said - the form constructor is private. It means you cannot create instance of the class. And then, we demand to allow somehow get an case. For this we have the static
.
We can already utilise the singleton now. If nosotros create a dummy file, we would get the singleton with the following code:
import ServerGlobal from ' ./server-global ' ; const instance = ServerGlobal . getInstance ()
Now let's manage the MongoDB connection and the winston logger setup. So nosotros want to connect to MongoDB and setup the logger ONLY One time - because, why would we want to institute connexion or setup the logger twice?
For this, nosotros tin can apply the form constructor. As we saw, the constructor would only run one time considering we only create i instance of the form.
So first thing - permit's connect to MongoDB using the mongoose package.
import mongoose from ' mongoose ' ; import winston from ' winston ' ; form ServerGlobal { individual static _instance : ServerGlobal ; private constructor () { mongoose . connect ( process . env . DB_ENDPOINT , { useNewUrlParser : true , useUnifiedTopology : true , useCreateIndex : true , useFindAndModify : false , }); } static getInstance () { if ( this . _instance ) { render this . _instance ; } this . _instance = new ServerGlobal (); return this . _instance ; } } export default ServerGlobal ;
That's all. Just nosotros missing i thing. What if the connectedness is either successfully setup or failed? We want to log information technology.
For this we would use form belongings to concord the winston logger object, and so we could use the logger in other places in the appliction:
import path from ' path ' ; import mongoose from ' mongoose ' ; import winston from ' winston ' ; class ServerGlobal { individual readonly _logger : winston . Logger ; private static _instance : ServerGlobal ; individual constructor () { this . _logger = winston . createLogger ({ level : ' info ' , format : winston . format . combine ( winston . format . timestamp (), winston . format . json (), ), transports : [ new winston . transports . Panel (), new winston . transports . File ({ filename : path . join ( __dirname , ' ../logs.log ' ), level : ' info ' , }), ], }); mongoose . connect ( process . env . DB_ENDPOINT , { useNewUrlParser : truthful , useUnifiedTopology : true , useCreateIndex : true , useFindAndModify : false , }). then (() => this . _logger . info ( ' MongoDB connectedness established successfully ' )) . take hold of (( due east : mongoose . Error ) => this . _logger . error ( `MongoDB connection failed with error: ${ e } ` )); } static getInstance () { if ( this . _instance ) { return this . _instance ; } this . _instance = new ServerGlobal (); return this . _instance ; } public get logger () { return this . _logger ; } } export default ServerGlobal ;
And then now information technology's all setup. The merely thing left is to create the singleton right when your server boots.
So assume you accept some server.ts
file in which you lot boot the server, and y'all as well want to log the boot and port. Then, the file would wait something like this:
import http from ' http ' ; import app from ' ./app ' ; import ServerGlobal from ' ./server-global ' ; const port = procedure . env . PORT ; app . set ( ' port ' , port ); const server = http . createServer ( app ); // Init global set up ServerGlobal . getInstance (); ServerGlobal . getInstance (). logger . info ( `Server is running on port ${ process . env . PORT } ` );
As yous can see, In the last 2 lines, we created the singleton, so logged the port on which the server listen (Annotation that the showtime line is actually redundant).
Finally, if you would like to log some actions besides in your RestAPI controller, you could exercise it by simply importing the ServerGlobal
and using its logger.
I practise recommend to take a look at the NestJS framework that as well using this pattern pattern using its Providers
.
How To Single Instance Service Node Js,
Source: https://dev.to/talr98/singleton-design-pattern-use-case-with-node-js-typescript-express-js-5ebb
Posted by: guoarron1960.blogspot.com
0 Response to "How To Single Instance Service Node Js"
Post a Comment