Open In App

Explain the concept of Domain in Node.js

Improve
Improve
Like Article
Like
Save
Share
Report

Introduction: The Node.js domain module is used to catch outstanding errors. Domains provide a way to handle multiple different input-output operations as a single group. If either the event emitter or the callback is registered in the domain and when an error event or throws an error,  the domain object is notified instead of losing the context of the error. The domain error handler is not a substitute for closing the process when an error occurs. The safest way to deal with a thrown error is to close it.  Bring down the process. It is recommended that a typical web server send an error response to the request that threw the error and allow it. Other members will finish at normal time and stop listening for new requests from this worker.

The unhandled error can be intercepted using internal binding or external binding.

  • Internal Binding: The error emitter executes the code within the domain’s run method. Executes a function provided in the domain context and implicitly binds event emitters, timers, and low-level requests created in that context. You can optionally pass arguments to the function.
  • External Binding: The error emitter is explicitly added to the domain using its add method. It explicitly adds an emitter to the domain. If the event handler called by the emitter throws an error, or if the emitter issues an “error” event, it will be forwarded to the domain’s “error” event, similar to the implicit binding. This also works with the timers returned by setInterval() and setTimeout(). When the callback function is invoked, it is caught by the domain’s “error” handler.

Syntax: To use the domain module we need to import it into our project directory. The syntax will be as follows: 

const domain = require("domain");

Note: According to the Official Nodejs documentation this domain model is pending deprecation. Once the replacement API is complete, this module will be completely deprecated. Users who absolutely need to have the functionality provided by the domain can trust it for now but expect to move to another solution in the future. Now we shouldn’t try to write new code with them. 

The domain class of the domain module is used to provide active domain objects with routing errors and uncaught exceptions. This is a subclass of EventEmitter. To handle the error you catch, listen for the error event. It is created with the following syntax.

const domain = require("domain");
const createdDomain = domain.create();

Example 1: This example will demonstrating the domain in Node.js:

Javascript




const EventEmitter = require("events").EventEmitter;
const domain = require("domain");
 
const emitterExplicit = new EventEmitter();
 
// Create a firstDomain for explicit binding
const firstDomain = domain.create();
 
firstDomain.on('error', function(err) {
   console.log("This error will be handled by
       using firstDomain ("+err.message+")");
});
 
// Explicit binding using add method
firstDomain.add(emitterExplicit);
 
emitterExplicit.on('error',function(err) {
   console.log("This error will be handled by
       using listener ("+err.message+")");
});
 
emitterExplicit.emit('error',new Error('listener will handle'));
emitterExplicit.removeAllListeners('error');
emitterExplicit.emit('error',new Error('firstDomain will handle'));
 
// Create secondDomain for implicit binding
const secondDomain = domain.create();
 
secondDomain.on('error', function(err) {
   console.log("This error will be handled by
       using secondDomain ("+err.message+")");
});
 
// Implicit binding using run method
secondDomain.run(function() {
   const emitterImplicit = new EventEmitter();
   emitterImplicit.emit('error',new Error('secondDomain
       will handle'));  
});
 
firstDomain.remove(emitterExplicit);
emitterExplicit.emit('error', new Error('Exception error
    message. The system may crash!'));


Steps to run the application: Write the below code in the terminal to run the server:

node index.js

Output:

 

Example 2: The server is created using the explicit binding method. You can use one domain for the HTTP server, or you can use a separate domain for each request. req, and res is also created in the scope of serverUsingDomain. However, it’s a good idea to first create a separate domain for each request and then add req and res to it.

Javascript




const domain = require('domain');
const http = require('http');
const serverUsingDomain = domain.create();
 
serverUsingDomain.run(() => {
  http.createServer((req, res) => {
 
    /* The server is created in the scope of
    serverUsingDomain. Req, and res is also
    created in the scope of serverUsingDomain.
    However, it's a good idea to first create
    a separate domain for each request and
    then add req and res to it. */
    const reqdomain = domain.create();
    reqdomain.add(req);
    reqdomain.add(res);
    reqdomain.on('error', (error) => {
      console.error('Error', error, req.url);
      try {
        res.writeHead(500).end('Some Error occurred.');
      } catch (error2) {
        console.error('Error is sending 500', error2, req.url);
      }
    });
  }).listen(5000, () => {
   console.log("Server is running on PORT 5000");
  });
});


Steps to run the application: Write the below code in the terminal to run the server:

node index.js

Output:

 

Method Available in Domain Module: – Let’s see some methods available in the domain module of Node.js.

  • domain.create(): It returns the domain. The Domain class encapsulates the functionality of routing errors and uncaught exceptions for active domain objects.
  • domain.add(emitter): It explicitly adds an emitter to the domain. If the event handler called by the emitter throws an error, or if the emitter issues an “error” event, it will be dispatched to the domain’s “error” event, similar to the implicit binding.
  • domain.run(function): Executes a function provided in the domain context and implicitly binds event emitters, timers, and low-level requests created in that context. You can optionally pass arguments to the function.
  • domain.bind(callback):  The function returned is a wrapper for the callback function provided. When the returned function is called, all thrown errors are propagated to the domain’s “error” event.
  • domain.intercept(callback): This method is similar to the domain.bind (callback). However,  it not only catches the error that occurred but also the Error object that is sent as the first argument of the function.
  • domain.enter(): The enter() method is used by the run(), bind(), and intercept() methods to set the active domain. Set domain.active and process.domain to the domain and implicitly push the domain to the domain stack managed by the domain module (see domain.exit() for more information on the domain stack). Calling enter () separates the domain-bound asynchronous call from the start of the chain of I / O operations.  
  • domain.exit(): The exit() method exits the current domain and removes it from the domain stack.
  • domain.remove(emitter): It is the opposite of domain.add(emitter). Removes domain processing from the specified emitter.


Last Updated : 06 Jul, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads