What is an unhandled promise rejection?

516,309

Solution 1

The origin of this error lies in the fact that each and every promise is expected to handle promise rejection i.e. have a .catch(...) . you can avoid the same by adding .catch(...) to a promise in the code as given below.

for example, the function PTest() will either resolve or reject a promise based on the value of a global variable somevar

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
}).catch(function () {
     console.log("Promise Rejected");
});

In some cases, the "unhandled promise rejection" message comes even if we have .catch(..) written for promises. It's all about how you write your code. The following code will generate "unhandled promise rejection" even though we are handling catch.

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
});
// See the Difference here
myfunc.catch(function () {
     console.log("Promise Rejected");
});

The difference is that you don't handle .catch(...) as chain but as separate. For some reason JavaScript engine treats it as promise without un-handled promise rejection.

Solution 2

This is when a Promise is completed with .reject() or an exception was thrown in an async executed code and no .catch() did handle the rejection.

A rejected promise is like an exception that bubbles up towards the application entry point and causes the root error handler to produce that output.

See also

Solution 3

Promises can be "handled" after they are rejected. That is, one can call a promise's reject callback before providing a catch handler. This behavior is a little bothersome to me because one can write...

var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });

... and in this case, the Promise is rejected silently. If one forgets to add a catch handler, code will continue to silently run without errors. This could lead to lingering and hard-to-find bugs.

In the case of Node.js, there is talk of handling these unhandled Promise rejections and reporting the problems. This brings me to ES7 async/await. Consider this example:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  let temp = await tempPromise;
  // Assume `changeClothes` also returns a Promise
  if(temp > 20) {
    await changeClothes("warm");
  } else {
    await changeClothes("cold");
  }

  await teethPromise;
}

In the example above, suppose teethPromise was rejected (Error: out of toothpaste!) before getRoomTemperature was fulfilled. In this case, there would be an unhandled Promise rejection until await teethPromise.

My point is this... if we consider unhandled Promise rejections to be a problem, Promises that are later handled by an await might get inadvertently reported as bugs. Then again, if we consider unhandled Promise rejections to not be problematic, legitimate bugs might not get reported.

Thoughts on this?

This is related to the discussion found in the Node.js project here:

Default Unhandled Rejection Detection Behavior

if you write the code this way:

function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  return Promise.resolve(tempPromise)
    .then(temp => {
      // Assume `changeClothes` also returns a Promise
      if (temp > 20) {
        return Promise.resolve(changeClothes("warm"));
      } else {
        return Promise.resolve(changeClothes("cold"));
      }
    })
    .then(teethPromise)
    .then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}

When getReadyForBed is invoked, it will synchronously create the final (not returned) promise - which will have the same "unhandled rejection" error as any other promise (could be nothing, of course, depending on the engine). (I find it very odd your function doesn't return anything, which means your async function produces a promise for undefined.

If I make a Promise right now without a catch, and add one later, most "unhandled rejection error" implementations will actually retract the warning when i do later handle it. In other words, async/await doesn't alter the "unhandled rejection" discussion in any way that I can see.

to avoid this pitfall please write the code this way:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  var clothesPromise = tempPromise.then(function(temp) {
    // Assume `changeClothes` also returns a Promise
    if(temp > 20) {
      return changeClothes("warm");
    } else {
      return changeClothes("cold");
    }
  });
  /* Note that clothesPromise resolves to the result of `changeClothes`
     due to Promise "chaining" magic. */

  // Combine promises and await them both
  await Promise.all(teethPromise, clothesPromise);
}

Note that this should prevent any unhandled promise rejection.

Solution 4

"DeprecationWarning: Unhandled promise rejections are deprecated"

TLDR: A promise has resolve and reject, doing a reject without a catch to handle it is deprecated, so you will have to at least have a catch at top level.

Solution 5

In my case was Promise with no reject neither resolve, because my Promise function threw an exception. This mistake cause UnhandledPromiseRejectionWarning message.

Share:
516,309

Related videos on Youtube

Mohammad Sadiqur Rahman
Author by

Mohammad Sadiqur Rahman

Love Programming.

Updated on September 02, 2021

Comments

  • Mohammad Sadiqur Rahman
    Mohammad Sadiqur Rahman over 2 years

    For learning Angular 2, I am trying their tutorial.

    I am getting an error like this:

    (node:4796) UnhandledPromiseRejectionWarning: Unhandled promise rejection (r                                                                                                     ejection id: 1): Error: spawn cmd ENOENT
    [1] (node:4796) DeprecationWarning: Unhandled promise rejections are deprecated.
    In the future, promise rejections that are not handled will terminate the Node.
    js process with a non-zero exit code.
    

    I went through different questions and answers in SO but could not find out what an "Unhandled Promise Rejection" is.

    Can anyone simply explain me what it is and also what Error: spawn cmd ENOENT is, when it arises and what I have to check to get rid of this warning?

    • Benjamin Gruenbaum
      Benjamin Gruenbaum almost 6 years
      I missed this question! I'm so sorry for this warning it's confusing - we really improved it in newer Node.js and we're making the whole thing much better soon!
    • Christophe Roussy
      Christophe Roussy over 5 years
    • Aven Desta
      Aven Desta about 4 years
      @BenjaminGruenbaum, is it fixed yet? I got the same error on node v12.16.1
    • Benjamin Gruenbaum
      Benjamin Gruenbaum about 4 years
      @Babydesta well, we show a better error now with a stack trace but we still don't crash node on unhandled rejections. We probably just need to open a PR to do that.
  • einstein
    einstein about 7 years
    It seems to work, if you add myFunc = myFunct.then... in the second example.
  • randomsock
    randomsock about 7 years
    @einstein it will appear to work because you are recreating the same chain as in the first example: var x = foo(); x = x.then(...); x = x.catch(...)
  • Simon Legg
    Simon Legg about 7 years
    @einstein In your unchained example, when you say "For some reason Java Script engine treats it as promise without un-handled promise rejection", isn't this because and exception could be thrown in the .then(() => {...}) which you aren't handling? I don't think this is doing the same thing as when you chain them. Is it?
  • Kevin Lee
    Kevin Lee almost 7 years
    @DKG Regarding your second point, catch is a syntax sugar for then(undefined, onRejected). Since your already called then on myfunc and that triggered an error, it's not going to call then(undefined, onRejected) on the same promise again.
  • Orilious
    Orilious almost 6 years
    Hey, you saved hours of work for me. now I catching problems like never before.
  • Alex75
    Alex75 over 4 years
    i don't know if may be any of help but ... have you tryed var x=myFunc.then(){}; x.catch(){}. this is the exact chain written in 2 separated lines ... this should work. ok same answer from @randomsock. :)