1

I'm struggling to figure out how to properly bubble errors with promises.

Specifically, what I'm talking about is a situation where there is nested promises. I want to be able to implictly pass the resolve and reject functions to the nested promise.

It'll be more obvious what I mean by showing some code.

The following is what I have been using successfully:

var asyncIsEven = function(number) {
  return new Promise(function(resolve, reject){
      if (number % 2 == 0) { return resolve(number) }
      else { return reject("number is odd") }
  })
}

var A = function (number) {
  return new Promise(function(resolve, reject){
    return asyncIsEven(number).then(resolve).catch(reject)
  })
}

Here, it seems pretty unnecessary to write then(resolve).catch(reject). I understand that I can just make function A return asyncIsEven(number), but there are situations when I want to provide a then function but have no need to provide a catch function (or vice versa).

What I've tried:

this works, but is not really what I want because I'm not providing a then handler to the nested callback

var A = function (number) {
  return Promise.all([asyncIsEven(number)])
}

// or alternatively
var A = function(number) {
  return asyncIsEven(number)
}

This is what I want to write, but it doesn't work

var A = function(number) {
  return new Promise(function(resolve, reject) {
    return asyncIsEven(number).then(resolve)
  })
}

When I say it "doesnt work", what I mean is that I cannot write the following:

A(2).then(function(number) {
  console.log(`${number} is even`)
}).catch(function(err) {
  console.log(err)
})

Because the catch function will never be called.

In other words - if I define function A to return asyncIsEven(number).then(resolve), how can I bubble errors from asyncIsEven up to the reject callback given to A?

max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • 2
    `A(3).then(function(number) { console.log(`${number} is even`) }).catch(function(err) { console.log(err) })` will take you in `catch-block` – Rayon Jun 08 '16 at 00:45
  • What you want to write always resolves, it never rejects, hence an error is never thrown from the `A()` method, so you simply can't write it like that, you have to reject if there is an error? On the other hand, the `A()` function seems superfluous – adeneo Jun 08 '16 at 00:47
  • If you find yourself using `new Promise` for anything other that wrapping a callback-based function call, you are almost always using `new Promise` in a place where you shouldn't. It'd a good way to accidentally discard errors like this. I don't understand why your first example isn't what you want, if you give more info that might make this easier to answer. – loganfsmyth Jun 08 '16 at 00:50
  • @adeneo this is not "practical" code, I just devised it to explain the conceptual issue. Providing `A(3)` with that definition of `A` will not call the `catch` method. Anyway, I think I figured it out, and I'm posting an answer. – max pleaner Jun 08 '16 at 00:51
  • I understand that it's not "practical", the practical thing to do inside `A()` would be just `return asyncIsEven(number)`, or even just call that function directly without another wrapper. If you want to wrap in a new Promise, you have to somehow both resolve and reject depending on the outcome. – adeneo Jun 08 '16 at 00:54
  • "*I understand that I can just make function A `return asyncIsEven(number)`, but there are situations when I want to provide a `then` function*" - please show us such an example of such a situtation. You still can simply `return` that promise. For your case (that you "want to write but doesn't work") you really can use `var A = asyncIsEven` (or the longer `function A(number) { return asyncIsEven(number); }`) and it *will* work. There doesn't seem to be any need to nest promises - and certainly you never have to call them from inside the `Promise` constructor. – Bergi Jun 08 '16 at 01:03

1 Answers1

0

In response to comments and the duplicate question, I can write the following answer:

Wrapping A's return value (or that of any function which returns a different Promise) with new Promise() or Promise.all is unnecessary.

Instead, just call return otherPromise().then(handler) and the reject function on otherPromise can be used with A().catch(handler).

When new Promise() is used to wrap this return value, the reject function on the inner promise will not bubble to A().catch(). However, using Promise.all to wrap the return value will bubble up the error.

max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • But you still can't write `A(2).then( (number) => console.log(number))` because `number` would now be an array, exactly the same as the example in your question using `Promise.all` ? – adeneo Jun 08 '16 at 01:00