54

Using the native (ES6) Promise. Should I reject with an Error:

Promise.reject(new Error('Something went wrong'));

Or should I just reject with a string:

Promise.reject('Something went wrong');

And what is the difference in browser behaviour?

Dominic
  • 62,658
  • 20
  • 139
  • 163
  • 1
    I don't think there is a difference. You simply reject with a *value*. What that value is and how it is supposed to be processed depends on your application. – Felix Kling Sep 24 '14 at 15:20
  • @FelixKling MDN does say *For debugging purposes, it is useful to make reason an instanceof Error* - it doesn't however say why, any ideas? – CodingIntrigue Sep 24 '14 at 15:21
  • @RGraham: Where does it say that? – Felix Kling Sep 24 '14 at 15:24
  • Sorry, on the docs page for [Promise.reject](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject#Using_the_static_Promise.reject_method) – CodingIntrigue Sep 24 '14 at 15:27
  • 1
    @RGraham: Probably for the reason Benjamin mentions in his answer, to get a stack trace. However, that's a characteristic of `Error`, not of passing an `Error` object to `.reject()`. The browser or JavaScript still doesn't care what you pass to `.reject()`. – Felix Kling Sep 24 '14 at 15:31
  • Just like you can throw strings, but shouldn't. – Benjamin Gruenbaum Sep 24 '14 at 15:43
  • You should use `new`: `Promise.reject(new Error('Something went wrong'));` – jib May 27 '15 at 00:40
  • 3
    Also, in practice, just `throw new Error('Something went wrong'));` because inside promise-chains and Promise constructor executor functions, this turns into a rejection. – jib May 27 '15 at 00:46
  • Related: [Throwing strings instead of Errors](http://stackoverflow.com/q/11502052/1048572) – Bergi Aug 25 '15 at 23:09

2 Answers2

51

Yes, the rejection reason most definitely should be wrapped in new Error(). A string is not an error, when you have errors usually it means something went wrong which means you'd really enjoy a good stack trace. No error - no stack trace.

Just like with try/catch, if you add .catch to a thrown rejection, you want to be able to log the stack trace, throwing strings ruins that for you.

I'm on mobile so this answer is rather short but I really can't emphasize enough how important this is. In large (10K+ LoC) apps stack traces in rejections really made the difference between easy remote bug hunting and a long night in the office.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Thanks I am also working on large apps glad that someone has had some practical experience with it – Dominic Sep 24 '14 at 15:56
  • In all honesty? Consider Bluebird, it has better stack traces, typed `catch`, and unhabdled rejection tracking which are all killer features for debugging. ES6 promises work well so far only in Firefox in our experience. – Benjamin Gruenbaum Sep 24 '14 at 16:04
  • 2022 update: Don't prefer bluebird, all the changes for debugging have been upstreamed to native promises. (Errors should 100% be wrapped in `new Error()`) – Benjamin Gruenbaum Jan 21 '22 at 19:50
  • 1
    Also if you're rethrowing an error in a function that wraps another promise, you can pass the error from the catch param as the cause like this: `.catch((err)=>{reject(new Error('message ...', {cause: err}))})` – Seangle Oct 03 '22 at 09:52
0

I'm recommending to use Error object only (not a string) for sending the reasons.

Justification

Other parts of code are generating the Errors inside the Promise rejection reason...

If some code fails the exception returns the Error object. Also if you will call any external library, which does not support the Promise, it will throw the Error object when something fails. If one of errors mentioned above occurs inside the Promise, it will be transformed into catch with Error object.

Therefore if you will use the string as promise rejection reason, you have to expect that the catch can occurs with your string (part of your code) or Error (when some general error occurs). So you will have to use ugly code (err.message || err) everywhere, when you have to handle the error.

Martin
  • 696
  • 6
  • 7