Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw inside a callback inside a promise [duplicate]

I know that stackoverflow is full of similar question and I've read a lot of them.

From what I got a throw inside a promise should reject it, as I can read in the documentation:

If the executor throws an exception, its value will be passed to the reject resolving function.

But even after read a lot of post about promises and throw I still don't understand the snippet of code I'm pasting and why it happens.

function foo(a, b, cb) {
  setTimeout(() => {
    cb('Inner error *!?"$%&#@"');
  }, 0);
}

const getThePromise = () => {
  return new Promise((resolve, reject) => {
    const cb = (err) => {

      /* >>> ************ */

      throw err;       // catch not called
      // reject(err);  // catch called

      /* ************ <<< */

    }
    foo('foo', 'dudee', cb);
  });
}

getThePromise()
.catch((err) => {
  console.log('CATCH:', err);
})
.then((res) => {
  console.log('then...');
})

I don't understand why if I use the throw the .catch of the promise is not called but if I use the reject it is called.

Just for sake of clarification I'm using Node.js v6.2.2 in a Mac OS/X 10.11 but I don't think it could be also a browser issue.

like image 370
nkint Avatar asked Aug 31 '16 09:08

nkint


People also ask

Is callback and promise same?

A callback function is passed as an argument to another function whereas Promise is something that is achieved or completed in the future. In JavaScript, a promise is an object and we use the promise constructor to initialize a promise.

How do you use callbacks with promises?

If the callback function returns non-error output, we resolve the Promise with the output. Let's start by converting a callback to a promise for a function that accepts a fixed number of parameters: const fs = require('fs'); const readFile = (fileName, encoding) => { return new Promise((resolve, reject) => { fs.

Is promise better than callback?

Promises are JavaScript objects that represent an eventual completion or failure of an asynchronous operation. A promise is a returned object where you attach callbacks, instead of passing callbacks into a function. the place where you attach the callback after a successful completion of a task is called, .


1 Answers

You are throwing your error inside an asynchronous setTimeout call, which will lead to an uncaught error. The asynchronous code will not execute in the same context as the try-catch block. This has nothing to do with the promise API. This is just part of the behavior of asynchronous code execution in JavaScript.

Take a look at the following example.

const asyncOperation = err => {
  try {
    setTimeout(function() {
      throw err; // will be dropped onto the event queue
      // until the call stack is empty
      // even if this takes longer than
      // a second.
    }, 1000);
  } catch (e) {
    console.log(e) // will not be called
  }
}

asyncOperation('Inner error *!?"$%&#@"')

And now the same example with the try-catch block inside the setTimeout call and the error being thrown inside the try block.

const asyncOperation = err => {
  setTimeout(function() {
    try {
      throw err // here the error will be throw inside
    } catch (e) { // the try block and has the same execution 
      console.log(e) // context.
    }
  }, 1000);
}

asyncOperation('Inner error *!?"$%&#@"')

You can find more information regarding the Promise.catch right here.

Promise.prototype.catch()

The catch() method returns a Promise and deals with rejected cases only.

There is actually an example with the same situation you are describing in your example. Check out

Gotchas when throwing errors

// Errors thrown inside asynchronous functions will act like uncaught errors
var p2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    throw 'Uncaught Exception!';
  }, 1000);
});

p2.catch(function(e) {
  console.log(e); // This is never called
});
like image 85
DavidDomain Avatar answered Oct 07 '22 12:10

DavidDomain