---
description: In previous tutorials, you would have seen callback functions which are used for Asynchronous events. But sometimes callback functions can become a nightmare when they start becoming nested, and the p
title: Node.js Promise Tutorial
image: https://www.guru99.com/images/node-js-promise-tutorial.png
---

 

[Skip to content](#main) 

**⚡ Smart Summary**

Promises in Node.js replace deeply nested callbacks with a returned object that settles once, so asynchronous database work reads as a flat chain of then clauses instead of a pyramid of anonymous functions.

* 🔘 **Callback problem:** Nested callbacks grow long and hard to maintain.
* ☑️ **Promise basics:** A promise returns a value and settles exactly once.
* ✅ **Chaining:** then itself returns a promise, so inserts run in order.
* 🧪 **Custom promises:** The q library denodeify wraps any callback.
* 🛠️ **Modern form:** async and await consume promises without then callbacks.
* 📊 **Error rule:** Unhandled rejections terminate Node.js since version 15.

[ Read More ](javascript:void%280%29;) 

![Node.js Promise Tutorial showing callbacks chained into promises](https://www.guru99.com/images/node-js-promise-tutorial.png) 

In previous tutorials, you would have seen callback functions which are used for Asynchronous events. But sometimes callback functions can become a nightmare when they start becoming nested, and the program starts to become long and complex.

## What are promises?

Before we start with promises, let’s first revisit what are “callback” functions in [Node.js](https://www.guru99.com/node-js-tutorial.html). We have seen these callback functions a lot in the previous chapters, so let’s quickly go through one of them.

The example below shows a code snippet, which is used to connect to a[ MongoDB ](https://www.guru99.com/mongodb-tutorials.html)database and perform an update operation on one of the records in the database.

[](https://www.guru99.com/images/NodeJS/010716%5F0659%5FNodejsTutor1.png)

1. In the above code, the part of the function(err,db) is known as the declaration of an anonymous or callback function. When the MongoClient creates a connection to the MongoDB database, it will return to the callback function once the connection operation is completed. So in a sense, the connection operations happen in the background, and when it is done, it calls our callback function. Remember that this is one of the key points of Node.js to allow many operations to happen concurrently and thus not block any user from performing an operation.
2. The second code block is what gets executed when the callback function is actually called. The callback function just updates one record in our MongoDB database.

So what is a promise then? Well, a promise is just an enhancement to callback functions in Node.js. During the development lifecycle, there may be an instance where you would need to nest multiple callback functions together. This can get kind of messy and difficult to maintain at a certain point in time. In short, a promise is an enhancement to callbacks that looks towards alleviating these problems.

The basic syntax of a promise is shown below;

var promise = doSomethingAync()
promise.then(onFulfilled, onRejected)

* “doSomethingAync” is any callback or asynchronous function which does some sort of processing.
* This time, when defining the callback, there is a value which is returned called a “promise.”
* When a promise is returned, it can have 2 outputs. This is defined by the ‘then clause’. Either the operation can be a success which is denoted by the ‘onFulfilled’ parameter. Or it can have an error which is denoted by the ‘onRejected’ parameter.

A [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global%5FObjects/Promise) sits in one of three states and settles once:

| State     | Meaning                          |
| --------- | -------------------------------- |
| Pending   | The work has not finished.       |
| Fulfilled | onFulfilled runs with the value. |
| Rejected  | onRejected runs with the error.  |

**Note:** So the key aspect of a promise is the return value. There is no concept of a return value when working with normal callbacks in Node.js. Because of the return value, we have more control of how the callback function can be defined.

**Version note:** these examples still run on Node.js 24, the Active LTS line in 2026\. Since Node.js 15 an [unhandled rejection](https://nodejs.org/api/cli.html) ends the process rather than printing a warning, so close every chain with .catch().

In the next topic, we will see an example of promises and how they benefit from callbacks.

## Callbacks to promises

Now let’s look at an example of how we can use “promises” from within a Node.js application. In order to use promises in a Node.js application, the ‘promise’ module must first be downloaded and installed.

We will then modify our code as shown below, which updates an EmployeeName in the ‘Employee’ collection by using promises.

**Step 1)** Installing the [NPM Modules](https://www.guru99.com/node-js-modules-create-publish.html)

To use Promises from within a Node.js application, the promise module is required. To install the promise module, run the below command

**npm install promise**

**Step 2)** Modify the code to include promises

[](https://www.guru99.com/images/NodeJS/010716%5F0659%5FNodejsTutor2.png)

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';

MongoClient.connect(url)
    .then(function(err, db) {
        db.collection('Employee').updateOne({
            "EmployeeName": "Martin"
        }, {
            $set: {
                "EmployeeName": "Mohan"
            }
        });
    }); 

**Code Explanation:**

1. The first part is to include the ‘promise’ module which will allow us to use the promise functionality in our code.
2. We can now append the ‘then’ function to our MongoClient.connect function. So what this does is that when the connection is established to the database, we need to execute the code snippet defined thereafter.
3. Finally, we define our code snippet which does the work of updating EmployeeName of the employee with the name of “Martin” to “Mohan”.

**Note:**

If you now check the contents of your MongoDB database, you will find that if a record with EmployeeName of “Martin” exists, it will be updated to “Mohan.”

To check that the data has been properly inserted in the database, you need to execute the following commands in MongoDB

1. use EmployeeDB
2. db.Employee.find({EmployeeName : “Mohan”})

The first statement ensures that you are connected to the EmployeeDB database. The second statement searches for the record which has the employee name of “Mohan”.

### RELATED ARTICLES

* [How to Download & Install Node.js and NPM on Windows ](https://www.guru99.com/download-install-node-js.html "How to Download & Install Node.js and NPM on Windows")
* [Node.js NPM Tutorial: How to Create, Extend, Publish modules ](https://www.guru99.com/node-js-modules-create-publish.html "Node.js NPM Tutorial: How to Create, Extend, Publish modules")
* [Create HTTP Web Server in Node.js with Code Example ](https://www.guru99.com/node-js-create-server-get-data.html "Create HTTP Web Server in Node.js with Code Example")
* [Bluebird NPM: Bluebird JS Promise with Example ](https://www.guru99.com/bluebird-promises.html "Bluebird NPM: Bluebird JS Promise with Example")

## Dealing with nested promises

When defining promises, it needs to be noted that the “then” method itself returns a promise. So in a sense, promises can be nested or chained to each other.

In the example below, we use chaining to define 2 callback functions, both of which insert a record into the MongoDB database.

(**Note**: Chaining is a concept used to link execution of methods to one another. Suppose if your application had 2 methods called ‘methodA’ and ‘methodB.’ And the logic was such that ‘methodB’ should be called after ‘methodA,’ then you would chain the execution in such a way that ‘methodB’ gets called directly after ‘methodA.’)

The key thing to note in this example is that the code becomes cleaner, readable and maintainable by using nested promises.

[](https://www.guru99.com/images/NodeJS/010716%5F0659%5FNodejsTutor3.png)

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url)

.then(function(db) {
    db.collection('Employee').insertOne({
        Employeeid: 4,
        EmployeeName: "NewEmployee"
    })

    .then(function(db1) {
        db1.collection('Employee').insertOne({
            Employeeid: 5,
            EmployeeName: "NewEmployee1"
        })
    })
});

**Code Explanation:**

1. We are now defining 2 “then” clauses which get executed one after the other. In the first then clause, we are passing the ‘db’ parameter which contains our database connection. We are then using the collection property of the ‘db’ connection to insert records into the ‘Employee’ collection. The ‘insertOne’ method is used to insert the actual document into the Employee collection.
2. We are then using the 2nd then clause also to insert another record into the database.

If you now check the contents of your MongoDB database, you will find the 2 records inserted into the MongoDB database.

**Modern equivalent:** async and await, standard since ES2017, consume these promises without then callbacks and have largely replaced [generator-based](https://www.guru99.com/node-js-generators-compare-callbacks.html) flow-control libraries such as co, while native Promise support makes q and bluebird redundant. The second block shows then receiving only db.

## Creating a custom promise

A custom promise can be created by using a Node.js module called ‘q.’ The ‘q’ library needs to be downloaded and installed using the Node Package Manager. After using the ‘q’ library, the method “denodeify” can be called which will cause any function to become a function which returns a promise.

In the example below, we will create a simple function called “Add” which will add 2 numbers. We will convert this function into a function to return a promise.

Once that is done, we will use the promise returned by the Add function to display a message in the console.log.

Let’s follow the below steps to creating our custom function to return a promise.

**Step 1)** Installing the NPM Modules

To use ‘q’ from within a Node.js application, the ‘q’ module is required. To install the ‘q’ module, run the below command

**npm install q**

**Step 2)** Define the following code which will be used to create the custom promise.

[](https://www.guru99.com/images/NodeJS/010716%5F0659%5FNodejsTutor7.png)

**Code Explanation:**

1. The first bit is to include the ‘q’ library by using the require keyword. By using this library, we will be able to define any function to return a callback.
2. We are creating a function called Add which will add 2 numbers defined in variables a and b. The sum of these values will be stored in variable c.
3. We are then using the q library to denodeify ( the method used to convert any function into a function that would return a promise) our Add function or in other words, convert our Add function to a function which returns a promise.
4. We now call our “Add” function and are able to get a return promise value because of the prior step we performed of denodeify the Add function.
5. The ‘then’ keyword is used to specify that if the function is executed successfully then display the string “Addition function completed” in the console.log.

When the above code is run, the output “Addition function completed” will be displayed in the console.log as shown below.

[](https://www.guru99.com/images/NodeJS/010716%5F0659%5FNodejsTutor8.png)

## FAQs

🧯 What happens if a rejection is never handled?

Since Node.js 15 the process exits with a non-zero code rather than warning. Attach .catch() to every chain, or register a [process handler](https://nodejs.org/api/cli.html) to log and recover.

🔗 How do .catch() and .finally() work in a chain?

.catch() receives any error thrown earlier in the chain, like a try block. .finally() runs whichever way the chain settled, so it suits closing a connection.

🚦 When should Promise.all, allSettled, race or any be used?

Promise.all fails fast if one input rejects. allSettled always resolves and reports every outcome. race adopts the first settled result. any needs one success, else throws AggregateError.

⚡ How does async and await differ from a then chain?

Both consume the same promise. await pauses inside an async function, so results land in ordinary variables and errors reach a try and catch block.

🌀 Do generators still matter for asynchronous Node.js code?

Rarely. [Generator](https://www.guru99.com/node-js-generators-compare-callbacks.html) functions with yield once drove libraries such as co, but async and await cover that job natively. Generators still suit lazy sequences and custom iterators.

🔧 Which modern helper replaces the q library wrapper?

util.promisify converts a callback-style function directly, and modules such as fs.promises already hand back promises. Both replace the q library shown above.

🤖 Can machine learning spot unhandled rejections and race conditions?

Yes. Machine-learned analysers flag chains with no rejection handler, awaits inside loops and order-dependent writes, then rank findings so [tests](https://www.guru99.com/node-js-testing-jasmine.html) hit the riskiest paths.

🧑‍💻 Can GitHub Copilot modernise legacy asynchronous code?

[GitHub Copilot](https://github.com/features/copilot) and similar agentic assistants rewrite nested callbacks as await calls quickly, yet each rewrite needs review because error paths and [route](https://www.guru99.com/node-js-express.html) semantics shift silently.

#### Summarize this post with:

ChatGPT Perplexity Grok Google AI 

**Stay Updated on AI** **Get Weekly AI Skills, Trends, Actionable Advice.** 

##### Sign up for the newsletter

Subscribe for Free 

You have successfully subscribed.  
Please check your inbox. 

![AI-Newsletter]() Chosen by over **350,000+** professionals 

[Scroll to top ](#wrapper)Scroll to top 

× 

Toggle Menu Close 

Search for: 

Search

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://www.guru99.com/#organization","name":"Guru99","sameAs":["https://www.facebook.com/Guru99Official","https://twitter.com/guru99com"],"logo":{"@type":"ImageObject","@id":"https://www.guru99.com/#logo","url":"https://www.guru99.com/images/guru99-logo-v1-150x59.png","contentUrl":"https://www.guru99.com/images/guru99-logo-v1-150x59.png","caption":"Guru99","inLanguage":"en-US"}},{"@type":"WebSite","@id":"https://www.guru99.com/#website","url":"https://www.guru99.com","name":"Guru99","publisher":{"@id":"https://www.guru99.com/#organization"},"inLanguage":"en-US"},{"@type":"ImageObject","@id":"https://www.guru99.com/images/node-js-promise-tutorial.png","url":"https://www.guru99.com/images/node-js-promise-tutorial.png","width":"700","height":"250","caption":"Node.js Promise Tutorial","inLanguage":"en-US"},{"@type":"BreadcrumbList","@id":"https://www.guru99.com/node-js-promise-generator-event.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":"1","item":{"@id":"https://www.guru99.com","name":"Home"}},{"@type":"ListItem","position":"2","item":{"@id":"https://www.guru99.com/node-js","name":"Node-JS"}},{"@type":"ListItem","position":"3","item":{"@id":"https://www.guru99.com/node-js-promise-generator-event.html","name":"Node.js Promise Tutorial"}}]},{"@type":"WebPage","@id":"https://www.guru99.com/node-js-promise-generator-event.html#webpage","url":"https://www.guru99.com/node-js-promise-generator-event.html","name":"Node.js Promise Tutorial","dateModified":"2026-07-30T20:12:23+05:30","isPartOf":{"@id":"https://www.guru99.com/#website"},"primaryImageOfPage":{"@id":"https://www.guru99.com/images/node-js-promise-tutorial.png"},"inLanguage":"en-US","breadcrumb":{"@id":"https://www.guru99.com/node-js-promise-generator-event.html#breadcrumb"}},{"@type":"Person","@id":"https://www.guru99.com/author/james","name":"James Hartman","description":"I am James Hartman, a seasoned professional in Oracle Certified Java Professional tutorials, specializing in crafting comprehensive guides to help you excel in your Java certification journey.","url":"https://www.guru99.com/author/james","image":{"@type":"ImageObject","@id":"https://www.guru99.com/images/james-hartman-author-v2-120x120.png","url":"https://www.guru99.com/images/james-hartman-author-v2-120x120.png","caption":"James Hartman","inLanguage":"en-US"},"worksFor":{"@id":"https://www.guru99.com/#organization"}},{"articleSection":"Node-JS","headline":"Node.js Promise Tutorial","description":"In previous tutorials, you would have seen callback functions which are used for Asynchronous events. But sometimes callback functions can become a nightmare when they start becoming nested, and the p","keywords":"nodejs","speakable":{"@type":"SpeakableSpecification","cssSelector":[".entry-title",".summary"]},"@type":"Article","author":{"@id":"https://www.guru99.com/author/james","name":"James Hartman"},"dateModified":"2026-07-30T20:12:23+05:30","image":{"@id":"https://www.guru99.com/images/node-js-promise-tutorial.png"},"copyrightYear":"2026","name":"Node.js Promise Tutorial","subjectOf":[{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"What happens if a rejection is never handled?","acceptedAnswer":{"@type":"Answer","text":"Since Node.js 15 the process exits with a non-zero code rather than warning. Attach .catch() to every chain, or register a process handler to log and recover."}},{"@type":"Question","name":"How do .catch() and .finally() work in a chain?","acceptedAnswer":{"@type":"Answer","text":".catch() receives any error thrown earlier in the chain, like a try block. .finally() runs whichever way the chain settled, so it suits closing a connection."}},{"@type":"Question","name":"When should Promise.all, allSettled, race or any be used?","acceptedAnswer":{"@type":"Answer","text":"Promise.all fails fast if one input rejects. allSettled always resolves and reports every outcome. race adopts the first settled result. any needs one success, else throws AggregateError."}},{"@type":"Question","name":"How does async and await differ from a then chain?","acceptedAnswer":{"@type":"Answer","text":"Both consume the same promise. await pauses inside an async function, so results land in ordinary variables and errors reach a try and catch block."}},{"@type":"Question","name":"Do generators still matter for asynchronous Node.js code?","acceptedAnswer":{"@type":"Answer","text":"Rarely. Generator functions with yield once drove libraries such as co, but async and await cover that job natively. Generators still suit lazy sequences and custom iterators."}},{"@type":"Question","name":"Which modern helper replaces the q library wrapper?","acceptedAnswer":{"@type":"Answer","text":"util.promisify converts a callback-style function directly, and modules such as fs.promises already hand back promises. Both replace the q library shown above."}},{"@type":"Question","name":"Can machine learning spot unhandled rejections and race conditions?","acceptedAnswer":{"@type":"Answer","text":"Yes. Machine-learned analysers flag chains with no rejection handler, awaits inside loops and order-dependent writes, then rank findings so tests hit the riskiest paths."}},{"@type":"Question","name":"Can GitHub Copilot modernise legacy asynchronous code?","acceptedAnswer":{"@type":"Answer","text":"GitHub Copilot and similar agentic assistants rewrite nested callbacks as await calls quickly, yet each rewrite needs review because error paths and route semantics shift silently."}}]}],"@id":"https://www.guru99.com/node-js-promise-generator-event.html#schema-1156603","isPartOf":{"@id":"https://www.guru99.com/node-js-promise-generator-event.html#webpage"},"publisher":{"@id":"https://www.guru99.com/#organization"},"inLanguage":"en-US","mainEntityOfPage":{"@id":"https://www.guru99.com/node-js-promise-generator-event.html#webpage"}}]}
```
