Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to reject/resolve a promise

Tags:

node.js

promise

q

I am thinking about when exactly I need to reject a promise. I found a couple of questions regarding this topic, but could not find a proper answer. When should I reject a promise?

This article http://howtonode.org/6666a4b74d7434144cff717c828be2c3953d46e7/promises says:

  • Resolve: A successful Promise is 'resolved' which invokes the success listeners that are waiting and remembers the value that was resolved for future success listeners that are attached. Resolution correlates to a returned value.
  • Reject: When an error condition is encountered, a Promise is 'rejected' which invokes the error listeners that are waiting and remembers the value that was rejected for future error listeners that are attached. Rejection correlates to a thrown exception.

Is this the principle guideline? That one only reject a promise if an exception occured?

But in case of a function like

findUserByEmail()

I'd would expect the function to return a user, so that I can continue the chain without verifying the result

findUserByEmail()
    .then(sendWelcomeBackEmail)
    .then(doSomeNiceStuff)
    .then(etc..)

What are best / common practises?

like image 697
Christopher Will Avatar asked Jun 25 '13 09:06

Christopher Will


People also ask

Can you reject a resolved Promise?

A Promise that is resolved with the given value, or the promise passed as value, if the value was a promise object. It may be either fulfilled or rejected — for example, resolving a rejected promise will still result in a rejected promise.

What happens if you don't reject a Promise resolve?

A promise is just an object with properties in Javascript. There's no magic to it. So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object.

How do you deal with resolve and reject in promises?

then() method should be called on the promise object to handle a result (resolve) or an error (reject). It accepts two functions as parameters. Usually, the . then() method should be called from the consumer function where you would like to know the outcome of a promise's execution.

What does rejecting a Promise do?

The Promise. reject() method is used to return a rejected Promise object with a given reason for rejection. It is used for debugging purposes and selective error catching.


1 Answers

In general you can think of rejecting as being analogous to a synchronous throw and fulfilling as being analogous to a synchronous return. You should reject whenever the function is unsuccessful in some way. That could be a timeout, a network error, incorrect input etc. etc.

Rejecting a promise, just like throwing an exception, is useful for control flow. It doesn't have to represent a truly unexpected error; it can represent a problem that you fully anticipate and handle:

function getProfile(email) {
  return getProfileOverNetwork(email)
    .then(null, function (err) {
      //something went wrong getting the profile
      if (err.code === 'NonExistantUser') {
        return defaultUser;
      } else if (profileCached(email)) {
        return getProfileFromCache(email);//fall back to cached profile
      } else {
        throw err;//sometimes we don't have a nice way of handling it
      }
    })
}

The rejection lets us jump over the normal success behavior until we get to a method that knows how to handle it. As another example, we might have some function that's deeply nested at the bottom of the applications stack, which rejects. This might not be handled until the very top of the stack, where we could log it. The point is that rejections travel up the stack just like exceptions do in synchronous code.

In general, wherever possible, if you are struggling to write some asynchronous code, you should think "what would I write if this were synchronous". It's usually a fairly simple transformation to get from that, to the promised equivalent.

A nice example of where rejected promises might be used is in an exists method:

function exists(filePath) {
  return stat(filePath) //where stat gets last updated time etc. of the file
    .then(function () { return true; }, function () { return false; })
}

Notice how in this case, the rejection is totally expected and just means the file does not exist. Notice also how it parallels the synchronous function though:

function existsSync(filePath) {
  try {
    statSync(filePath);
    return true;
  } catch (ex) {
    return false;
  }
}

Your Example

Returning to your example:

I would normally chose to reject the promise resulting from findUserByEmail if no user was found. It's something you fully expect to happen sometimes, but it's the exception from the norm, and should probably be handled pretty similarly to all other errors. Similarly if I were writing a synchronous function I would have it throw an exception.

Sometimes it might be useful to just return null instead, but this would depend on your applications logic and is probably not the best way to go.

like image 145
ForbesLindesay Avatar answered Nov 02 '22 22:11

ForbesLindesay