javascriptpromise

JavaScript Promises - reject vs. throw


I have read several articles on this subject, but it is still not clear to me if there is a difference between Promise.reject vs. throwing an error. For example,

Using Promise.reject

return asyncIsPermitted()
    .then(function(result) {
        if (result === true) {
            return true;
        }
        else {
            return Promise.reject(new PermissionDenied());
        }
    });

Using throw

return asyncIsPermitted()
    .then(function(result) {
        if (result === true) {
            return true;
        }
        else {
            throw new PermissionDenied();
        }
    });

My preference is to use throw simply because it is shorter, but was wondering if there is any advantage of one over the other.


Solution

  • There is no advantage of using one vs the other, but, there is a specific case where throw won't work. However, those cases can be fixed.

    Any time you are inside of a promise callback, you can use throw. However, if you're in any other asynchronous callback, you must use reject.

    For example, this won't trigger the catch:

    new Promise(function() {
      setTimeout(function() {
        throw 'or nah';
        // return Promise.reject('or nah'); also won't work
      }, 1000);
    }).catch(function(e) {
      console.log(e); // doesn't happen
    });

    Instead you're left with an unresolved promise and an uncaught exception. That is a case where you would want to instead use reject. However, you could fix this in two ways.

    1. by using the original Promise's reject function inside the timeout:

    new Promise(function(resolve, reject) {
      setTimeout(function() {
        reject('or nah');
      }, 1000);
    }).catch(function(e) {
      console.log(e); // works!
    });

    1. by promisifying the timeout:

    function timeout(duration) { // Thanks joews
      return new Promise(function(resolve) {
        setTimeout(resolve, duration);
      });
    }
    
    timeout(1000).then(function() {
      throw 'worky!';
      // return Promise.reject('worky'); also works
    }).catch(function(e) {
      console.log(e); // 'worky!'
    });