-1

I'm using Q together with RequireJS. Oftentimes I find myself writing code like this:

function someFunc() {

  // prepare result
  var res = Q.defer();

  require( ['someOtherModule'], function( mod ) {

    // do some stuff with mod
    mod().then( function(){

          // ...
          return somePromise;

        })
        .then( function( val ) {

          // resolve the functions deferred
          res.resolve( val );

        }, function( err ){

          // relay error
          res.reject( err );

        });

  });

  // return promise
  return res.promise;

}

So i have a function someFunc(), which requests a module (it may determine at runtime, which module to load) and then does some stuff with that module possibly using a promise chain itself (in the example just one element in the chain, but can be more).

In the end I just want to relay the results of my inner promise chain to the outer deferred/promise.

I know I could resolve with the promise itself like this

res.resolve( 
      mod().then( function(){

            // ...
            return somePromise;

          })
    );

But when the chain gets longer or includes more code, this will be hardly readable.

I'm basically looking for a method/way to do something like this:

mod().then( function(){

      // ...
      return somePromise;

    })
    .relay( res );

Which would be equivalent to the above code wrt to maintaining errors within the promise chain.

I already looked into Q.nfcall() or Q.nfapply(), but those only work for callbacks, which have to parameters error and result. In the case of a require() call, however, the parameters are the requested module, which does not comply with the signature Q wants to have ...

Sirko
  • 72,589
  • 19
  • 149
  • 183
  • It seems you can just use `mod.then(....).then(res.resolve, res.reject)` to transform the promise's result, as `res.resolve` and `res.reject` accept the first param as given result, the promise would call them and pass the `result/error` to them. – fuyushimoya Aug 17 '15 at 10:05

1 Answers1

2

The point is that you should not nest your chain inside the require callback. Promisify at the lowest level:

function requirePromise(dep) {
    var res = Q.defer();
    require([dep], function(mod) {
        res.resolve(mod);
    });
    return res.promise;
}

Then you can use this in a flat chain like you want:

requirePromise('someOtherModule').then(function(mod) {
    …
    return somePromise;
});

"Relaying" a promise into a deferred that does wait for it is basically the deferred antipattern with inversed notation. Notice that if you really wanted such a method, it would just look like

Promise.prototype.relay = function(def) {
    return def.resolve(this);
};
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Just to make sure, I understood you correctly. This would transform my above code to something like this, right? http://pastebin.com/3w7qbFR6 – Sirko Aug 17 '15 at 11:18
  • Exactly, you can strip out the `requirePromise` function if you don't need to do it multiple times – Bergi Aug 17 '15 at 11:57