You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Promise异步代码抛出异常无法被catch捕获的原因及JSON.parse异常处理方案咨询

Why Async Errors in Promise Executors Aren't Caught by .catch()

Great question—this boils down to how Promise error handling works, and what contexts it can track. Let's break this down step by step.

1. Why setTimeout throws can't be caught by Promise .catch()

A Promise's executor function (the (resolve, reject) => {} callback you pass to new Promise()) runs synchronously when the Promise is created. The Promise can only automatically catch exceptions that occur during this synchronous execution phase.

When you throw an error inside setTimeout, that code runs later, in a separate macro task. By the time that throw happens, the Promise's executor has already finished running, and the error is no longer in the Promise's context—it's thrown into the global scope instead. The Promise's .catch() has no way to listen for errors from arbitrary async tasks like timers.

On the flip side, calling reject(new Error(5)) inside setTimeout works because you're explicitly telling the Promise to enter a rejected state. reject() is a function tied directly to the Promise instance, so even when called asynchronously, it properly routes the error into the Promise's chain, making it available to .catch().

2. JSON.parse errors in XHR callbacks: Do they get caught by Promise .catch()?

Short answer: No, they won't be caught automatically.

Your xhr.onreadystatechange callback is an asynchronous event handler, just like the setTimeout callback. When JSON.parse() throws an error here, it's happening outside the Promise executor's synchronous context, so the Promise has no way to pick it up. That error would bubble up to the global scope (and likely log an uncaught error in the console) instead of triggering your Promise's .catch().

How to fix this: Wrap JSON.parse() in try/catch

You do need to explicitly handle parsing errors with a try/catch block, then pass the error to reject() to add it to the Promise chain. Here's your modified code with this fix:

function APIRequest(){
  return new Promise((resolve,reject)=>{
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
      if (xhr.readyState == 4) {
        if (xhr.status >= 200 && xhr.status < 299 || xhr.status == 304) {
          try {
            let response = JSON.parse(xhr.responseText);
            resolve(response);
          } catch (parseError) {
            reject(parseError); // Send parsing error to Promise's catch()
          }
        } else {
          reject(new Error('Something went wrong')); // Use Error objects for better error context
        }
      }
    };
    xhr.open('GET','URL_REQUEST');
    xhr.send(null);
  });
}

Is there a more concise way?

If you were using fetch() instead of XHR, the .json() method returns a Promise that automatically rejects on parsing errors, which makes this cleaner. But since you're working with XHR, the try/catch approach is the most straightforward and reliable way to handle parsing errors.

Another alternative is to wrap the entire callback logic in a try/catch, but targeting just the JSON.parse() call is more precise.

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:57:44