Creating a (ES6) promise without starting to resolve it

Good question!

The resolver passed to the promise constructor intentionally runs synchronous in order to support this use case:

var deferreds = [];
var p = new Promise(function(resolve, reject){
    deferreds.push({resolve: resolve, reject: reject});
});

Then, at some later point in time:

 deferreds[0].resolve("Hello"); // resolve the promise with "Hello"

The reason the promise constructor is given is that:

  • Typically (but not always) resolution logic is bound to the creation.
  • The promise constructor is throw safe and converts exceptions to rejections.

Sometimes it doesn't fit and for that it the resolver runs synchronously. Here is related reading on the topic.


I want to add my 2 cents here. Considering exactly the question "Creating a es6 Promise without starting resolve it" I solved it creating a wrapper function and calling the wrapper function instead. Code:

Let's say we have a function f which returns a Promise

/** @return Promise<any> */
function f(args) {
   return new Promise(....)
}

// calling f()
f('hello', 42).then((response) => { ... })

Now, I want to prepare a call to f('hello', 42) without actually solving it:

const task = () => f('hello', 42) // not calling it actually

// later
task().then((response) => { ... })

Hope this will help someone :)


Referencing Promise.all() as asked in the comments (and answered by @Joe Frambach), if I want to prepare a call to f1('super') & f2('rainbow'), 2 functions that return promises

const f1 = args => new Promise( ... )
const f2 = args => new Promise( ... )

const tasks = [
  () => f1('super'),
  () => f2('rainbow')
]

// later
Promise.all(tasks.map(t => t()))
  .then(resolvedValues => { ... })

How about a more comprehensive approach?

You could write a Constructor that returns a new Promise decorated with .resolve() and .reject() methods.

You would probably choose to name the constructor Deferred - a term with a lot of precedence in [the history of] javascript promises.

function Deferred(fn) {
    fn = fn || function(){};

    var resolve_, reject_;

    var promise = new Promise(function(resolve, reject) {
        resolve_ = resolve;
        reject_ = reject;
        fn(resolve, reject);
    });

    promise.resolve = function(val) {
        (val === undefined) ? resolve_() : resolve_(val);
        return promise;//for chainability
    }
    promise.reject = function(reason) {
        (reason === undefined) ? reject_() : reject_(reason);
        return promise;//for chainability
    }
    promise.promise = function() {
        return promise.then(); //to derive an undecorated promise (expensive but simple).
    }

    return promise;
}

By returning a decorated promsie rather than a plain object, all the promise's natural methods/properties remain available in addition to the decorations.

Also, by handling fn, the revealer pattern remains availble, should you need/choose to use it on a Deferred.

DEMO

Now, with the Deferred() utility in place, your code is virtually identical to the jQuery example.

var deferreds = {};
function waitFor(key: string): Promise<any> {
  if (key in promises) {
    return deferreds[key].promise();
  }
  var def = Deferred();    
  deferreds[key] = def;
  return def.promise();
}

Things are slowly getting better in JavaScript land, but this is one case where things are still unnecessarily complicated. Here's a simple helper to expose the resolve and reject functions:

Promise.unwrapped = () => {
  let resolve, reject, promise = new Promise((_resolve, _reject) => {
    resolve = _resolve, reject = _reject
  })
  promise.resolve = resolve, promise.reject = reject
  return promise
}

// a contrived example

let p = Promise.unwrapped()
p.then(v => alert(v))
p.resolve('test')

Apparently there used to be a Promise.defer helper, but even that insisted on the deferred object being separate from the promise itself...