javascriptpromisebluebird

Can I do a "lazy" promise with Bluebird.js?


I want a construct similar to promise that waits until then is called before it runs. That is, if I never actually call then, the promise will never run.

Is this possible?


Solution

  • Make a function which creates and returns a promise on first invocation, but returns the same promise on each subsequent invocation:

    function getResults() {
      if (getResults.results) return getResults.results;
    
      getResults.results = $.ajax(...); # or where ever your promise is being built
    
      return getResults.results;
    }
    

    Promises don't work in such a way that they could support lazy loading. Promises are created by asynchronous code in order to communicate a result. Until the async code has been invoked, there simply is no promise.

    You could certainly write a promise-like object which did lazy invocation, but code that generated these promises would be very different:

    // Accepts the promise-returning function as an argument
    LazyPromise = function (fn) {
      this.promise = null;
      this.fn = fn
    }
    
    LazyPromise.prototype.then = function () {
      this.promise = this.promise || fn();
      this.promise.then.apply(this.promise, arguments)
    }
    
    // Instead of this...
    var promise = fn();
    
    // You'd use this:
    var promise = new LazyPromise(fn);
    

    It's better in this uncommon use to make the actual creation of the promise lazy (as in either above example), rather than trying to make promises themselves responsible for lazy-evaluation.