raffomania
raffomania

Reputation: 461

Why does deferred.resolve not behave as specified in the q manual?

This may be a stupid question, but I am unable to wrap my head around this.

Consider the following piece of code:

function throwError() {
    throw Error("can't touch this.");
}

var def = q.defer();

def.promise.then(
  function() {
    console.log("no error");
  },
  function() {
    console.log("error");
  }
);

q.fcall(throwError).then(def.resolve, def.resolve).done();

In my opinion this should print error. Instead, it prints no error. The q manual states:

The reject function is a shorthand for resolving with a rejected promise.

q.fcall(throwError) should produce a rejected promise, so the deferred should be rejected, right?

Please note that this is a purely hypothetical question, I know that this would not be used in the real world.

Upvotes: 0

Views: 236

Answers (1)

loganfsmyth
loganfsmyth

Reputation: 161517

The issue here seems to be around the language used, so I'm going to try to break it down a bit more to make it clearer. When you call

var rejected = q.fcall(throwError);

then rejected is indeed a rejected promise. What you are then doing is

var def = q.defer();
def.promise.then(
  function(arg1) {
    console.log("no error");
  },
  function(arg2) {
    console.log("error");
  }
);

rejected.then(
  function(){
    def.resolve();
  },
  function(err){
    def.resolve(err); // err === new Error();
  }
);

When a promise is rejected, it will run the rejection callback, triggering def.resolve(err);. Q has no knowledge that def is anything other that some random arugment, so you might as well be calling def.resolve('random');. You are resolving def with some argument. In this case, it happens to be an instance of Error. That means that your no error callback will be called, and arg1 === new Error().

So now, given the documentation quote you mentioned

The reject function is a shorthand for resolving with a rejected promise.

what are you are doing is essentially transforming the rejected promise rejected into the promise def.promise which will always be fulfilled, but where the fulfillment handler will receive an error as the first argument.

To achieve what you are expecting, you need to properly make def.promise be rejected. You can accomplish this two ways.

  1. Reject it using def.reject(err);.
  2. As your quote says, resolve it with a rejected promise, def.resolve(rejected);.

Upvotes: 1

Related Questions