4

Given

(async () => {
 const p = await new Promise((resolve, reject) => setTimeout(() => {
    reject(new Error(1))
  }, Math.floor(Math.random() * 1000))); return p})()
.then(data => console.log(data))
.catch(err => console.error(err));

the Error() is logged at .catch()

If we extend the pattern to use a loop the Error is logged at .catch()

const fn = async(res, ...props) => {
  for (let prop of props) res.push(await prop())
  return res
}

const arr = [
  () =>
    new Promise((resolve, reject) => 
      setTimeout(() =>
        reject(new Error(1))
      , Math.floor(Math.random() * 1000))
    ),
  () => 
    new Promise((resolve, reject) => 
      setTimeout(() => 
        resolve(1) 
      , Math.floor(Math.random() * 1000))
    )
  ];

fn([], ...arr)
.then(data => console.log(data))
.catch(err => console.log(err));

If we use a loop to call more than one function which returns a Promise and do not explicitly pass Error() to reject() of Promise constructor resolver function .catch() does not catch the error, and array res is not returned, only the Promise value passed to resolve() is available at

const fn = async(res, ...props) => {
  for (let prop of props) res.push(await prop())
  return res
}

const arr = [
  () =>
    new Promise((resolve, reject) => 
      setTimeout(() =>
        reject(1)
      , Math.floor(Math.random() * 1000))
    ),
  () => 
    new Promise((resolve, reject) => 
      setTimeout(() => 
        resolve(1) 
      , Math.floor(Math.random() * 1000))
    )
  ];

fn([], ...arr)
// what happened to our array `res` returned from `fn`?
.then(data => console.log(data))
// what happened to our rejected Promise?
.catch(err => console.log(err)); 

Questions:

  1. Why does reject() call not propagate to .catch() when Error() is not explicitly passed to reject() within Promise constructor within a loop at an async function?

  2. Why is only a single Promise value returned to .then() though an array is returned from the async function when one of the Promise objects iterated at a loop reject() function is called within Promise constructor resolver function?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
guest271314
  • 1
  • 15
  • 104
  • 177
  • 1
    `fn` throws with the first iterations `await prop()` ... hence why the last catch outputs the `1` (it's the last catch that is called, not the last then) – Jaromanda X Aug 01 '17 at 06:56
  • 1
    @JaromandaX A good reason to use `console.error()` instead of `console.log()` at `.catch()`. Can you post your comment as an Answer? – guest271314 Aug 01 '17 at 06:57

2 Answers2

4

If we […] do not explicitly pass Error() to reject() of Promise constructor resolver function .catch() does not catch the error

Sure, because there is no Error then. But catch will catch whatever you pass to reject, which is the value 1, which does get logged correctly.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • The issue was user error in reading the response. To prevent the user error in the future: 1) explicitly pass `Error()` when and error is expected, and 2) use `console.error()` instead of `console.log()` at `.catch()` to distinguish resolve and rejected `Promise` value where the values might happen to be the same. – guest271314 Aug 02 '17 at 13:56
0

When trying code, for example where Promise is used, and an error is expected to be logged at .catch(), explicitly pass Error(), preferably with a relevant message as parameter, to reject() of Promise constructor or Promise.reject(); and substitute using console.error() for console.log() at .catch(), for the purpose of distinguishing the error that you are expecting to be logged as an Error() and not a resolved Promise value, where the resolved and rejected value may happen to be the same.

guest271314
  • 1
  • 15
  • 104
  • 177