1

Dear participants please tell me the solution.

In this block of code, the catсh method perfectly catches the exception:

const myPromise = new Promise(() => {
  throw new Error(`Oops! Threw an exception`);
});

// We catch the exception in the method `catch`.
myPromise
  .catch((error) => console.log(error.message));

And in this block, the catсh method will not be called:

сonst TIMEOUT = 1000;

const mySecondPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    throw new Error(`Error in asynchronous function`);
  },
  TIMEOUT
  );
});

mySecondPromise
  .catch(() => console.log(`This code will not be executed`));

Please explain:

  1. Why is this happening (I suppose this is due to Event Loop)?
  2. How to rewrite the code so that catching an exception in the catch method works with setTimeout?

Thank you all for the answers!

Here is a life example:

import moment from "moment";

const Delay = (timeout, timePress) => {
    return new Promise((res => setTimeout(() => {
            res(`${moment().format("LTS")} ${timeout} ${timePress}`);
        }, timeout * 1000)
    ));
};

export default Delay;

I want, If for some reason an exception is thrown in the setTimeout function, I should be able to catch it. Like this:

Delay.catch(() => console.log(`This code will not be executed`));
  • Can you show the rest of your real code so we can see what you're really trying to do? Answering this in the abstract doesn't let us help you with the best design for the real problem and the best way to use promises for this. – jfriend00 May 09 '20 at 15:24
  • I supplemented my question with a real example – Sergey Isaev May 09 '20 at 15:49
  • If you want the delay promise to reject, you declare the second argument for the `new Promise((resolve, reject) => { /* code here */})` executor function and you just call `reject()`, the same as if you want the promise to resolve. If you actually want to use exceptions inside the `setTimeout()`, then you need a `try/catch` inside the callback that will call `reject()` if someone throws. – jfriend00 May 09 '20 at 15:56
  • I understood you. Many thanks! What about such a decision? Declare ```const Delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));``` then make a call ```Delay.then(`${moment().format("LTS")} ${timeout} ${timePress}`).catch(() => console.log(`This code will not be executed`));``` – Sergey Isaev May 09 '20 at 16:09
  • I'm sorry, but `Delay.then(\`${moment().format("LTS")} ${timeout} ${timePress}\`)` does not make any sense to me. First off, `Delay` is a function so you need to call it with `Delay()`. Then, you pass a function reference to `.then()`, not a string. – jfriend00 May 09 '20 at 16:19
  • @jfriend00. Excuse me. My mistake by carelessness. You're right. The code should look like this: ```const Delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));``` And ```Delay(timeout).then(() => console.log(`${moment().format("LTS")} ${timeout} ${timePress}`)).catch(()=>console.log(`This code will not be executed`));``` Here is the working code: https://codesandbox.io/s/hardcore-mclaren-79smp?file=/src/index.js – Sergey Isaev May 09 '20 at 17:17
  • Yes, of course the `.catch()` won't be executed because your promise doesn't reject. It resolves. I'm not sure what you are confused about in that regard. – jfriend00 May 09 '20 at 18:36
  • It 's okay, I just wanted to make sure the code above solves my task. Thank you for a meaningful conversation! – Sergey Isaev May 10 '20 at 00:09

2 Answers2

4

The timeout code is executed outside the promise context. What you want to do is call 'reject' with the error:

const TIMEOUT = 1000;

const mySecondPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error(`Error in asynchronous function`));
  },
  TIMEOUT
  );
});

mySecondPromise
  .catch(() => console.log(`This code WILL be executed`));
Jason Goemaat
  • 28,692
  • 15
  • 86
  • 113
0

After some discussions and comments, my task was solved by this approach:

const someFunction = timeout => new Promise(resolve => setTimeout(resolve, timeout));

someFunction(timeout).then(() => doSomething()).catch(() => console.log(`This code will not be executed`));

If an exception occurs in an asynchronous function:

someFunction(timeout).then(ErrorEvent).catch(() => console.log(`This code will not be executed`));

Such solutions are still possible:

const testF = () => { throw new Error(`Упс! Бросили исключение.`) }

const genPromise = () => new Promise((resolve, reject) => {
    setTimeout(() => {
        try {
            const res = testF()
            resolve(res)
        } catch (e) { reject(e) }
    }, 1e3)
})

t1: {
    const log = console.log.bind(console, 't1:')
    const _then = log.bind(console, 'then:')
    const _catch = log.bind(console, 'catch:')

    genPromise()
        .then(_then)
        .catch(_catch)
        .then(_then)
}

t2: {
    const log = console.log.bind(console, 't2:')
    const _then = log.bind(console, 'then:')
    const _catch = log.bind(console, 'catch:')

    void async function () {
        let pRes = null
        try {
            pRes = await genPromise()
        } catch (e) {
            _catch(e.message)
        }
        _then(pRes)
    }()
}