Bluebird NPM: Bluebird JS Promise with Example

โšก Smart Summary

Bluebird JS is a fully featured Promise library for JavaScript whose defining capability is promisification: converting callback-based Node modules into promise-returning ones, so an entire library such as the MongoDB driver can be used asynchronously.

  • ๐Ÿ”ต Core Capability: promisifyAll wraps every method of a module, appending an Async suffix that signals the method now returns a promise.
  • ๐Ÿ“ฆ Installation: A single npm install bluebird command adds the library, after which require exposes the Promise object.
  • ๐Ÿ”— Chaining: Each then receives the previous resolution value, which replaces nested callbacks with a flat sequence of steps.
  • ๐Ÿท๏ธ Naming Rule: Only the Async-suffixed variants return promises; the original callback methods remain unchanged alongside them.
  • ๐Ÿ›ก๏ธ Failure Path: A single catch at the end of a chain receives rejections from every preceding step.
  • โš–๏ธ Modern Context: Native promises and async await now cover most of what Bluebird once uniquely provided.

Bluebird JS Promises

What is Bluebird JS?

Bluebird JS is a fully featured Promise library for JavaScript. Its strongest feature is that it allows you to โ€œpromisifyโ€ other Node modules in order to use them asynchronously. Promisify is a concept applied to callback functions, and it ensures that every callback function which is called returns a value.

So if a Node.js module contains a callback function which does not return a value, promisifying that module automatically modifies all the functions in it so that each one returns a value.

This means you can use Bluebird to make the MongoDB module run asynchronously, which adds another level of ease when writing Node.js applications.

The example below first establishes a connection to the โ€œEmployeeโ€ collection in the โ€œEmployeeDBโ€ database. Once the connection is established, it retrieves all of the records in the collection and displays them in the console.

How to Generate Promises with Bluebird JS Library

Here is a step by step example showing how to generate promises with the Bluebird JS library.

Step 1) Installing the NPM modules

To use Bluebird from within a Node application, the Bluebird module is required. Install it with the command below:

npm install bluebird

Step 2) Include the Bluebird module

The next step is to include the Bluebird module in your code and promisify the entire MongoDB module. Promisifying here means Bluebird ensures that every method defined in the MongoDB library returns a promise.

Include Bluebird modules

Code Explanation:

  1. The require command includes the Bluebird library.
  2. Bluebird’s .promisifyAll() method creates an async version of every method the MongoDB module provides, so each one runs in the background and returns a promise.

Step 3) Connect to the database

The final step is to connect to the database, retrieve all the records in the collection, and display them in the console log.

Connect to the Database

Code Explanation:

  1. Notice the connectAsync method is used instead of the normal connect method. Bluebird appends the Async suffix to each method in the MongoDB library to distinguish the calls that return promises from those that do not. Methods without the Async suffix carry no such guarantee.
  2. Similar to connectAsync, the findAsync method returns all of the records in the MongoDB โ€œEmployeeโ€ collection.
  3. If findAsync resolves successfully, the following block iterates through each record in the collection and displays it in the console log.

If the steps above are carried out properly, all of the documents in the Employee collection are displayed in the console, as shown in the output below.

Bluebird promises output

Here is the complete code for reference:

var Promise = require('bluebird');

// promisifyAll adds an Async variant of every MongoDB method
var mongoClient = Promise.promisifyAll(require('mongodb')).MongoClient;

mongoClient.connectAsync('mongodb://localhost/EmployeeDB')

    .then(function(db) {
        return db.collection('Employee').findAsync({});
    })
    .then(function(cursor) {
        cursor.each(function(err, doc) {
            console.log(doc);
        });
    });

โš ๏ธ Driver version note: the code above targets MongoDB Node driver 2.x, where connect resolves with a database object. From driver 3.0 onward it resolves with a MongoClient, so the chain must call client.db('EmployeeDB').collection('Employee') instead of db.collection('Employee'). Modern driver versions also return native promises already, which makes promisifyAll unnecessary for MongoDB specifically.

Bluebird vs Native Promises: Which to Use

When Bluebird was first written, Node had no promise support at all, so the library filled a genuine gap in the platform. Node has shipped native promises since version 4 and async/await since version 7.6, which changes the calculation considerably for anyone starting a project today.

Aspect Bluebird Native Promises
Dependency An npm package to install and maintain Built into the runtime
Promisifying callbacks promisifyAll() converts a whole module util.promisify() converts one function
Extra helpers map, filter, props, each, timeout, cancellation all, allSettled, any, race only
Long stack traces Yes, when enabled Improved but shorter
Best for Legacy callback libraries, concurrency helpers New code, and anything using async await

Choose native promises for new work, since they need no dependency and integrate directly with async await. Reach for Bluebird when a dependency still exposes callbacks only, or when its concurrency helpers, such as Promise.map with a concurrency limit, save a meaningful amount of code.

How to Handle Errors with Bluebird Promises

The example above has no failure path. If MongoDB is not running, or the collection name is wrong, the chain rejects and nothing is printed โ€” the process simply exits with no explanation. Every promise chain needs a terminal handler.

Bluebird supports .catch() for rejections and .finally() for cleanup that must run either way. It also supports typed catches, which handle one class of error while letting others propagate.

var Promise = require('bluebird');
var mongoClient = Promise.promisifyAll(require('mongodb')).MongoClient;

var connection;

mongoClient.connectAsync('mongodb://localhost/EmployeeDB')
    .then(function(db) {
        connection = db;
        return db.collection('Employee').findAsync({});
    })
    .then(function(cursor) {
        return cursor.toArrayAsync();
    })
    .then(function(docs) {
        docs.forEach(function(doc) { console.log(doc); });
    })
    .catch(Promise.TimeoutError, function(err) {
        console.error('The database did not respond in time.');
    })
    .catch(function(err) {
        // Any other rejection from any step above arrives here
        console.error('Query failed:', err.message);
    })
    .finally(function() {
        // Runs on success and on failure, so the socket always closes
        if (connection) { connection.close(); }
    });

Three habits matter here. First, place .catch() at the end rather than after each step, because one terminal handler receives rejections from every preceding link in the chain. Second, use .finally() for releasing resources such as a database connection, since it runs on both the success and failure paths. Third, never leave a chain without a catch: an unhandled rejection terminates the Node process on current versions, and Bluebird will print an explicit warning about it beforehand. Enabling long stack traces during development with Promise.config({ longStackTraces: true }) makes the origin of a rejection far easier to locate.

Common Bluebird Promisify Errors and Fixes

Most Bluebird problems come from the promisified naming convention, or from mixing the callback and promise calling styles in the same chain, rather than from any fault in the library itself. Each symptom below names its cause and its fix.

  • โ€œconnectAsync is not a functionโ€: the module was required directly instead of through promisifyAll(), so no Async variants exist. Wrap the require call as shown above.
  • Calling the plain method and getting undefined: connect() still expects a callback. Only the Async-suffixed copy returns a promise.
  • Passing a callback to an Async method: supply neither a callback nor await and the promise resolves unobserved. Use one style per call, not both.
  • promisifyAll on an already promise-based library: harmless but pointless, and it produces confusing double-suffixed names. Check the library documentation first.
  • Losing errors silently: a chain with no .catch() hides the rejection reason until Node reports an unhandled rejection and exits. Always terminate the chain with a catch, even in short scripts.

FAQs

promisifyAll adds a copy of each method rather than replacing it, so the original callback version keeps working. The Async suffix marks the promise-returning copy. The suffix is configurable through the promisifier option.

Yes. Bluebird promises are Promises/A+ compliant, so await accepts them exactly like native ones. This lets you promisify a legacy module and then consume it with modern syntax.

Yes. AI assistants rewrite nested callbacks into promise chains or async await reliably. Verify error handling afterwards, because generated conversions frequently drop the terminal catch.

AI tools trace which link in a chain lacks a return statement, the usual cause of a rejection escaping. They also flag chains missing a terminal catch, which is what turns a handled error into a crash.

Promise.all waits on an existing array of promises. Bluebird’s Promise.map builds them from values and accepts a concurrency limit, which prevents thousands of simultaneous requests from exhausting sockets.

Summarize this post with: