最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why a promise reject is not catched within a try catch block but produces an Uncaught error? - Stack Overflow

programmeradmin0浏览0评论

I'm facing a promise rejection that escapes a try catch block. The rejection causes an Uncaught exception which is something I can not prehend.

If I add a reject handler in the Promise.then or a Promise.catch, the rejection gets captured. But I was hopping try catch will work in this situation.

What is happening here?

class HttpResponse {
    json() {
        return Promise.reject('parse error')
    }
}

function fetch() {
        return new HttpResponse();
}


const res = fetch();

try {
    res.json().then(json => {
        alert(`json: ${json}`);
    }
    //,reason => {
    //    alert(`promise.reject ${reason}`);
    //}
    )
    //.catch(reason => {
    //    alert(`promise.catch ${reason}`);
    //})
} catch (e) {
    alert(`catch{} from try catch: ${e}`);
}

I'm facing a promise rejection that escapes a try catch block. The rejection causes an Uncaught exception which is something I can not prehend.

If I add a reject handler in the Promise.then or a Promise.catch, the rejection gets captured. But I was hopping try catch will work in this situation.

What is happening here?

class HttpResponse {
    json() {
        return Promise.reject('parse error')
    }
}

function fetch() {
        return new HttpResponse();
}


const res = fetch();

try {
    res.json().then(json => {
        alert(`json: ${json}`);
    }
    //,reason => {
    //    alert(`promise.reject ${reason}`);
    //}
    )
    //.catch(reason => {
    //    alert(`promise.catch ${reason}`);
    //})
} catch (e) {
    alert(`catch{} from try catch: ${e}`);
}

Share Improve this question edited Sep 6, 2021 at 14:43 Daniel San asked Oct 27, 2020 at 20:58 Daniel SanDaniel San 2,0363 gold badges21 silver badges39 bronze badges 1
  • Does this answer your question? Catching Errors in JavaScript Promises with a First Level try ... catch – thesecretmaster Commented Sep 5, 2021 at 1:52
Add a ment  | 

3 Answers 3

Reset to default 2

Promises have their own mechanism of handling errors with the catch() method. A try / catch block can't control what's happening when chaining methods.

function fetch() {
  return Promise.reject('parse error');
}

const res = fetch();
res.then(json => {
  console.log(`json: ${json}`);
}).catch((e) => {
  console.log(`catch{} from chained catch: ${e}`);
});

However, using async / await changes that. There you don't use the methods of a promise but handle errors with a try / catch block.

function fetch() {
  return Promise.reject('parse error');
}

(async function() {
  try {
    const res = await fetch();
  } catch (e) {
    console.log(`catch{} from try catch: ${e}`);
  }
})();

The technical reason behind this behavior is that a JavaScript promise invokes one of two callback functions for success or failure.

A promise does not emit an Error that is required for the try to work. it is not an Error (or more technically accurate) an instance of Error. It emits an event. You are encouraged to emit a new Error() if you need it to emit one. As pointed out here: https:developer.mozilla/en-US/docs/Web/JavaScript/Reference/…

It emits an event that you can set up a handler for: https://developer.mozilla/en-US/docs/Web/API/PromiseRejectionEvent –

Finally, await throws an Error as described in the spec: https://tc39.es/ecma262/#await-rejected

Technical reasons behind:

HostPromiseRejectionTracker is an implementation-defined abstract operation that allows host environments to track promise rejections.

An implementation of HostPromiseRejectionTracker must plete normally in all cases. The default implementation of HostPromiseRejectionTracker is to unconditionally return an empty normal pletion.

https://www.ecma-international/ecma-262/10.0/index.html#sec-host-promise-rejection-tracker

Basically javascript engines can freely implement this spec. In the case of browsers you don't get the Error captured inside the try/catch because the error is not emitted where you think it should be. But instead it's tracked with this special event that throws the error in the console. Also on nodejs, this event causes the process to exit if you have node set to exit on unhandled exceptions.

On the other side, if you instead use async/await, the rejection is treated like an 'error' in practical terms. Meaning that the newer async/await feature behaves in a different fashion showing that it is not only syntactic sugar for Promises.

https://tc39.es/ecma262/#sec-throwpletion

In sum, if you use Promise.then you are forced to provide a reject argument or chain it with .catch to have the rejection captured or else it will reach the console and in case of nodejs to exit the process if configured to do so (I believe new nodejs does this by default). But if you use the newer async/await syntax you not only have a concise code (which is secondary) but a better rejection handling because it can be properly nested in a try/catch and it will behave like an standard Error.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论