Bluebird Promise Library

repository·master·Indexed 12 days ago

https://github.com/petkaantonov/bluebird

A high-performance, feature-rich Promises/A+ 1.1 compliant implementation for JavaScript. Version 3.7.2 provides advanced utilities, monitoring, and debugging tools. While optimized for performance, the maintainers recommend native Promises for modern applications unless legacy support or specific debugging features are required.

Tokens
61.6K
Snippets
210
Records
258
Agent score
87%

What's inside Bluebird

  1. Overview of Bluebird Promise Library

    master

    Bluebird is a fully featured promise library designed with a focus on performance and innovative features. It is Promises/A+ 1.1 compliant.

    Important Usage Note: It is highly recommended to use native Promises instead of Bluebird whenever possible. Native Promises are stable in modern Node.js and browser environments and offer high performance. Bluebird should primarily be used if you need to support very old browsers, End-of-Life (EoL) Node.js versions, or as an intermediate step to utilize Bluebird's warnings and monitoring features to identify bugs in your code.

  2. Why use Bluebird promises

    master

    Bluebird is a pragmatic, high-performance promise library designed for real-world asynchronous JavaScript. Developers choose Bluebird over native promises or other third-party libraries for the following reasons:

    • Performance: Optimized for server-side applications with minimal overhead, aiming for a "zero cost abstraction."
    • Debugging: Features superior cross-platform long stack traces and a built-in warning system to catch common promise usage mistakes. Unhandled errors are reported with helpful stack traces rather than being silently swallowed.
    • Compatibility: It is fully Promises/A+ spec compliant and can be used as a drop-in replacement for native promises to gain an instant performance boost.
    • Reliability: Provides a consistent experience across almost all platforms (including older environments like IE) and focuses on features with high synergy and composability rather than theoretical bloat.
  3. Prevent resource leaks with Promise.using and disposers

    master

    When managing multiple asynchronous resources (like database connections and file reads) concurrently using Promise.all or .spread, a failure in one resource acquisition can prevent the cleanup logic of another from ever running, leading to resource leaks (e.g., exhausting a connection pool).

    To solve this while retaining concurrency, Bluebird provides two key mechanisms:

    1. Disposers: Objects that wrap a resource along with a method to release it.
    2. Promise.using: A function that accepts disposers and automatically calls their release methods regardless of whether the subsequent operations succeed or fail.

    Instead of manually calling .finally() on individual resources, pass your resource-acquisition promises as arguments to Promise.using. The callback function will receive the resolved resources, and Bluebird ensures they are disposed of correctly.

    var using = Promise.using;
    
    using(
        getConnection(),
        fs.readFileAsync("file.sql", "utf8"), 
        function(connection, fileContents) {
            return connection.query(fileContents);
        }
    ).then(function() {
        console.log("query successful and connection closed");
    });
  4. How to abstract Dialogs using a base class

    master

    For complex UI interactions like prompts, progress bars, or confirmation dialogs, use an abstraction layer. Create a base Dialog class that manages callbacks and returns a Promise, then extend it with specific implementations (e.g., PromptDialog, NotifyDialog).

    The Dialog Interface

    A base Dialog should implement:

    • setCallbacks(okCallback, cancelCallback): Sets the internal functions to be called on user success or cancellation.
    • waitForUser(): Returns a Promise that resolves/rejects when the callbacks are triggered.
    • show(message): Displays the dialog (returns this for chaining).
    • hide(): Hides the dialog (returns this for chaining).

    Implementation Pattern

    1. Base Class: Defines the lifecycle and the waitForUser() method.
    2. Subclass: Inherits from the base, manages specific DOM elements, and implements show() and hide(). It calls this._okCallback() or this._cancelCallback() when the specific UI events occur.
    // Base Dialog Abstraction
    function Dialog() {
      this.setCallbacks(function() {}, function() {});
    }
    Dialog.prototype.setCallbacks = function(okCallback, cancelCallback) {
      this._okCallback     = okCallback;
      this._cancelCallback = cancelCallback;
      return this;
    };
    Dialog.prototype.waitForUser = function() {
      var _this = this;
      return new Promise(function(resolve, reject) {
        _this.setCallbacks(resolve, reject);
      });
    };
    Dialog.prototype.show = function() { return this; };
    Dialog.prototype.hide = function() { return this; };
    
    // Concrete Implementation
    function PromptDialog() {
      Dialog.call(this);
      this.el = document.getElementById('dialog');
      // ... setup elements ...
    }
    PromptDialog.prototype = Object.create(Dialog.prototype);
    PromptDialog.prototype.show = function(message) {
      // ... logic to show dialog ...
      return this;
    };
    
    // Usage with Method Chaining
    var prompt = new PromptDialog();
    
    prompt.show('What is your name?')
      .waitForUser()
      .then(function(name) {
        console.log(name);
      })
      .catch(function() {
        console.log('Cancelled');
      })
      .finally(function() {
        prompt.hide();
      });
  5. Understand benchmark metrics and environment

    master

    When running Bluebird benchmarks, the following metrics and environment details are provided:

    • time(ms): The execution time in milliseconds.
    • memory(MB): The highest snapshotted RSS memory (process.memoryUsage().rss) recorded during processing.
    • Platform info: Details about the OS, Node.js version, V8 version, and CPU used during the benchmark run.

    Note that latency benchmarks for fast promise implementations are generally not included here as they are primarily determined by the scheduler; for latency-specific testing, tools like JSPerfs are recommended.

  6. How cancellation works with multiple consumers

    master

    When a promise has multiple consumers (e.g., multiple .then() calls on the same promise), Bluebird tracks the number of consumers.

    • If one consumer calls .cancel(), that specific consumer's handlers will not be called.
    • The underlying operation (and the propagation of the cancellation signal) will only be aborted once all consumers have signaled cancellation.
    • This prevents one consumer from accidentally aborting a request that another consumer is still actively using.
  7. Understanding the benefits of long stack traces

    master

    Long stack traces provide a much clearer debugging experience by showing the actual sequence of asynchronous calls that led to an error, rather than just the internal Bluebird promise machinery.

    Without long stack traces, error stacks often point to internal library functions like _resolvePromise or _resolveLast. With long stack traces enabled, the stack includes the 'From previous event' context, allowing you to trace the error back through the original asynchronous chain.

    // Example of how long stack traces improve error visibility
    Promise.config({ longStackTraces: true });
    
    Promise.resolve().then(function outer() {
        return Promise.resolve().then(function inner() {
            return Promise.resolve().then(function evenMoreInner() {
                a.b.c.d() // This will throw a ReferenceError
            }).catch(function catcher(e) {
                console.error(e.stack);
            });
        });
    });