最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS中try-catch異常處理機制詳解(結(jié)合?async/await)

 更新時間:2026年01月13日 09:56:14   作者:愛吃草莓軟糖  
這篇文章主要介紹了JS中try-catch異常處理機制(結(jié)合?async/await)的相關(guān)資料,try...catch語句將能引發(fā)錯誤的代碼放在try塊中,并且對應(yīng)一個響應(yīng),然后有異常被拋出,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

前言

try-catch 是 JavaScript 中處理同步 / 異步異常的核心機制,尤其在 async/await 語法中,它是兜底異步錯誤的 “標準操作”。本文從底層機制核心用法、async/await 適配、常見誤區(qū)四個維度,把 try-catch 講透。

一、try-catch 基礎(chǔ)機制:“捕獲 - 處理” 的核心邏輯

1. 本質(zhì)作用

try-catch 用于捕獲代碼執(zhí)行過程中拋出的異常,避免異常向上冒泡導(dǎo)致程序崩潰,同時允許開發(fā)者自定義錯誤處理邏輯。

  • 類比生活:你嘗試用微波爐熱飯(try 塊),如果微波爐壞了(拋出異常),你不會干等著,而是換用燃氣灶(catch 塊兜底);不管熱飯成功與否,最后都要關(guān)掉電源(finally 塊收尾)。

2. 語法結(jié)構(gòu)

try {
  // 可能拋出異常的代碼(同步/await 異步)
} catch (error) {
  // 只有 try 塊拋出異常時,才執(zhí)行這里(處理錯誤)
} finally {
  // 可選:無論是否拋出異常,最終一定會執(zhí)行(收尾操作)
}

3. 底層執(zhí)行流程

  1. 執(zhí)行 try 塊內(nèi)的代碼;
  2. 如果 try 塊內(nèi)沒有拋出異常:跳過 catch 塊,執(zhí)行 finally 塊(若有),然后繼續(xù)執(zhí)行后續(xù)代碼;
  3. 如果 try 塊內(nèi)拋出異常:立即停止 try 塊剩余代碼,跳轉(zhuǎn)到 catch 塊,傳入異常對象,執(zhí)行錯誤處理邏輯;執(zhí)行完 catch 后,再執(zhí)行 finally 塊(若有);
  4. finally 塊是 “最終保障”:即使 try/catch 內(nèi)有 return,也會先執(zhí)行 finally 再返回。

二、try-catch 處理同步異常(基礎(chǔ)場景)

同步代碼的異常(比如變量未定義、類型錯誤),會立即拋出,可被 try-catch 直接捕獲:

示例 1:捕獲基礎(chǔ)語法錯誤

function syncErrorDemo() {
  try {
    console.log("開始執(zhí)行同步代碼");
    // 拋出同步異常:訪問未定義的變量
    console.log(nonExistVar); 
    console.log("這行代碼不會執(zhí)行"); // 異常后停止執(zhí)行
  } catch (error) {
    // 捕獲異常并解析
    console.log("捕獲到同步異常:");
    console.log("錯誤類型:", error.name); // ReferenceError
    console.log("錯誤信息:", error.message); // nonExistVar is not defined
    console.log("調(diào)用棧:", error.stack); // 定位錯誤位置(調(diào)試關(guān)鍵)
  } finally {
    console.log("finally:同步代碼執(zhí)行收尾\n");
  }
}
 
syncErrorDemo();

執(zhí)行結(jié)果

開始執(zhí)行同步代碼
捕獲到同步異常:
錯誤類型: ReferenceError
錯誤信息: nonExistVar is not defined
調(diào)用棧: ReferenceError: nonExistVar is not defined at syncErrorDemo (...)
finally:同步代碼執(zhí)行收尾

示例 2:手動拋出異常(throw 關(guān)鍵字)

開發(fā)者可通過 throw 主動拋出異常(自定義錯誤),同樣會被 catch 捕獲:

function validateAge(age) {
  try {
    if (age < 18) {
      // 手動拋出自定義 Error 對象(推薦)
      throw new Error("年齡必須≥18歲");
    }
    console.log("年齡驗證通過");
  } catch (error) {
    console.log("驗證失?。?, error.message);
  }
}
 
validateAge(16); // 驗證失?。耗挲g必須≥18歲
validateAge(20); // 年齡驗證通過

三、try-catch 處理異步異常(核心:適配 async/await)

1. 異步異常的特殊性

普通異步代碼(比如 setTimeout 回調(diào)、Promise 回調(diào))的異常,無法被外層同步的 try-catch 捕獲—— 因為異步代碼執(zhí)行時,外層 try-catch 早已執(zhí)行完畢:

// 錯誤示例:同步 try-catch 捕獲不到異步回調(diào)的異常
function wrongAsyncCatch() {
  try {
    setTimeout(() => {
      // 異步回調(diào)內(nèi)的異常,外層 try-catch 捕獲不到
      throw new Error("異步回調(diào)出錯");
    }, 1000);
  } catch (error) {
    console.log("捕獲到錯誤:", error); // 永遠不會執(zhí)行
  }
}
wrongAsyncCatch(); // 控制臺會拋出“未捕獲的異常”

2. async/await 讓 try-catch 能捕獲異步異常

async/await 是 Promise 的語法糖,它將 “異步代碼同步化”——await 會暫停 async 函數(shù)執(zhí)行,直到 Promise 狀態(tài)變更;如果 Promise 被 reject(或異步代碼拋出異常),會像同步異常一樣拋出,此時 try-catch 就能捕獲:

核心示例:捕獲 await 異步錯誤

// 模擬異步操作(返回 Promise)
function fetchData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url === "success") {
        resolve({ data: "請求成功", code: 200 });
      } else {
        // Promise reject 會被 await 轉(zhuǎn)化為同步異常
        reject(new Error("接口請求失?。?04 Not Found"));
      }
    }, 1000);
  });
}
 
// async/await + try-catch 捕獲異步異常
async function asyncAwaitCatch() {
  try {
    console.log("開始請求接口");
    // await 等待 Promise,若 reject 則拋出異常
    const res = await fetchData("fail"); 
    console.log("接口返回:", res); // 異常后不會執(zhí)行
  } catch (error) {
    // 捕獲異步異常(等同于 Promise 的 .catch())
    console.log("捕獲到異步異常:", error.message);
    // 錯誤兜底:使用默認數(shù)據(jù)
    const defaultData = { data: "默認數(shù)據(jù)", code: 500 };
    console.log("兜底方案:", defaultData);
  } finally {
    console.log("finally:請求流程收尾(關(guān)閉加載彈窗)");
  }
}
 
asyncAwaitCatch();

執(zhí)行結(jié)果

開始請求接口
捕獲到異步異常:接口請求失?。?04 Not Found
兜底方案: { data: '默認數(shù)據(jù)', code: 500 }
finally:請求流程收尾(關(guān)閉加載彈窗)

3. 多異步操作的異常捕獲策略

場景捕獲方式適用場景
串行異步(依賴執(zhí)行)單個 try-catch 包裹所有 await一個失敗則整體失?。ū热绫韱翁峤唬?/td>
串行異步(獨立執(zhí)行)每個 await 單獨 try-catch單個失敗不影響其他(比如多商品下單)
并行異步(Promise.all)try-catch 包裹 Promise.all所有操作必須成功(比如批量校驗)
并行異步(允許部分失?。?/td>Promise.allSettled + 解析結(jié)果部分失敗不影響整體(比如批量查詢)

示例:并行異步的異常處理(Promise.all + try-catch)

async function parallelCatch() {
  try {
    // Promise.all 中任意一個 Promise reject,整體就會拋出異常
    const [res1, res2] = await Promise.all([
      fetchData("success"), // 成功
      fetchData("fail")     // 失敗
    ]);
    console.log("并行請求成功:", res1, res2);
  } catch (error) {
    console.log("并行請求失敗:", error.message);
    // 兜底:重新請求失敗的接口
    const backupRes = await fetchData("success");
    console.log("兜底成功:", backupRes);
  }
}
parallelCatch();

四、try-catch 的關(guān)鍵特性與常見誤區(qū)

1. 關(guān)鍵特性

(1)catch 只能捕獲 “拋出的異常”

只有通過 throw 或 Promise reject 明確拋出的異常,才能被 catch 捕獲;靜默失敗(比如函數(shù)返回 undefined)不會觸發(fā) catch:

try {
  const res = undefined; // 靜默失敗,無異常拋出
  if (!res) {
    console.log("數(shù)據(jù)為空,但未拋出異常");
  }
} catch (error) {
  console.log("不會執(zhí)行這里");
}

(2)finally 塊的 “優(yōu)先級”

即使 try/catch 內(nèi)有 return,也會先執(zhí)行 finally 再返回:

function finallyPriority() {
  try {
    return "try 返回值";
  } catch (e) {
    return "catch 返回值";
  } finally {
    console.log("finally 先執(zhí)行");
  }
}
console.log(finallyPriority()); // 輸出:finally 先執(zhí)行 → try 返回值

(3)Error 對象的核心屬性

catch 捕獲的 error 是 Error 實例(推薦用 new Error() 創(chuàng)建),包含三個核心屬性:

  • name:錯誤類型(比如 ReferenceError、TypeError、Error);
  • message:錯誤描述信息(自定義 / 內(nèi)置);
  • stack:錯誤調(diào)用棧(定位錯誤位置,調(diào)試必備)。

2. 常見誤區(qū)

誤區(qū) 1:用 try-catch 捕獲所有異步錯誤(包括非 await 異步)

// 錯誤:try-catch 捕獲不到非 await 的 Promise 異常
async function wrongCatch() {
  try {
    // 未用 await,Promise 異常會“逃逸”
    fetchData("fail"); 
  } catch (error) {
    console.log("捕獲不到:", error);
  }
}
wrongCatch(); // 控制臺拋出未捕獲的異常

解決:必須用 await 等待 Promise,才能讓異常被 try-catch 捕獲。

誤區(qū) 2:忽略 finally 塊的資源釋放

// 錯誤:請求失敗時,未關(guān)閉加載彈窗
async function noFinally() {
  console.log("打開加載彈窗");
  try {
    await fetchData("fail");
  } catch (error) {
    console.log("請求失敗");
    // 忘記關(guān)閉彈窗
  }
  // 如果沒有 catch,彈窗永遠不會關(guān)閉
}

解決:把 “資源釋放 / 收尾操作” 放在 finally 塊(比如關(guān)閉彈窗、清除定時器)。

誤區(qū) 3:catch 塊只打印日志,不處理錯誤

// 低效:只打印日志,沒有兜底邏輯
async function uselessCatch() {
  try {
    await fetchData("fail");
  } catch (error) {
    console.log("出錯了:", error); // 僅打印,無兜底
  }
  // 后續(xù)代碼依賴接口數(shù)據(jù),會繼續(xù)報錯
  console.log(res.data); // res 未定義
}

解決:catch 塊要做 “兜底處理”(比如賦值默認數(shù)據(jù)、重試請求、提示用戶)。

五、try-catch 與 Promise.catch 的對比(async/await 場景)

在 async/await 中,try-catch 等價于 Promise 的 .catch(),但更符合 “同步思維”:

特性try-catch(async/await)Promise.catch()
代碼可讀性高(線性代碼,無嵌套)低(鏈式調(diào)用)
錯誤處理范圍可包裹多個 await 操作只能處理單個 Promise
同步 / 異步錯誤捕獲同時支持僅支持 Promise 異常
調(diào)試體驗更友好(調(diào)用棧清晰)鏈式調(diào)用易丟失上下文

等價示例

// 1. try-catch 寫法(推薦)
async function tryCatchDemo() {
  try {
    const res = await fetchData("fail");
  } catch (e) {
    console.log("捕獲錯誤:", e.message);
  }
}
 
// 2. Promise.catch 寫法(等價)
async function promiseCatchDemo() {
  const res = await fetchData("fail").catch(e => {
    console.log("捕獲錯誤:", e.message);
  });
}

六、總結(jié):try-catch 核心使用原則

  1. 同步代碼:所有可能拋出異常的邏輯(比如參數(shù)校驗、DOM 操作),都用 try-catch 包裹;
  2. async/await 異步代碼:必須用 try-catch 包裹 await 操作(或外部加 .catch()),避免未捕獲的異步異常;
  3. finally 必用場景:涉及資源占用的操作(比如打開彈窗、創(chuàng)建定時器、請求接口),一定要在 finally 中釋放 / 收尾;
  4. catch 塊要 “有用”:不僅要捕獲錯誤,還要做兜底處理(默認值、重試、用戶提示),而非僅打印日志;
  5. 錯誤類型細化:可通過 error.name 區(qū)分錯誤類型,做針對性處理(比如網(wǎng)絡(luò)錯誤重試、業(yè)務(wù)錯誤提示)。

try-catch 不是 “萬能的”,但它是 JS 中最基礎(chǔ)、最可靠的異常處理方式 —— 尤其是在 async/await 場景下,掌握它就能解決 90% 以上的異常處理問題。

到此這篇關(guān)于JS中try-catch異常處理機制(結(jié)合 async/await)的文章就介紹到這了,更多相關(guān)JS try-catch異常處理機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

托克托县| 醴陵市| 浦东新区| 儋州市| 志丹县| 长白| 开化县| 白山市| 沁水县| 中西区| 颍上县| 大宁县| 巩义市| 扶风县| 河池市| 闽侯县| 清徐县| 武邑县| 乐平市| 邵东县| 肥西县| 叶城县| 延津县| 德令哈市| 八宿县| 鸡东县| 石渠县| 河北区| 朔州市| 上栗县| 舒兰市| 旺苍县| 宁蒗| 虎林市| 房产| 佳木斯市| 宝清县| 治县。| 息烽县| 平凉市| 教育|