偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

try...catch 抓不到 Promise 的錯(cuò)誤?原來(lái)是這么回事

開(kāi)發(fā)
在 JavaScript 中,try...catch 是我們處理錯(cuò)誤的得力助手。但當(dāng)你開(kāi)始和 Promise 打交道時(shí),可能會(huì)遇到一個(gè)讓你困惑的場(chǎng)景。

在 JavaScript 中,try...catch 是我們處理錯(cuò)誤的得力助手。我們很自然地認(rèn)為,只要把可能出錯(cuò)的代碼放進(jìn) try 塊,catch 就一定能捕獲到異常。但當(dāng)你開(kāi)始和 Promise 打交道時(shí),可能會(huì)遇到一個(gè)讓你困惑的場(chǎng)景:

try {
 // 假設(shè)這是一個(gè)會(huì)失敗的 API 請(qǐng)求
 fetch('https://non-existent-url.com/api'); 
 console.log('請(qǐng)求已發(fā)送');
} catch (error) {
 // 這里的 catch 會(huì)執(zhí)行嗎?
 console.log('抓到錯(cuò)誤了!', error);
}

// 控制臺(tái)輸出:
// 請(qǐng)求已發(fā)送
// Uncaught (in promise) TypeError: Failed to fetch

咦?catch 塊根本沒(méi)有執(zhí)行!錯(cuò)誤信息直接在控制臺(tái)炸開(kāi)了,帶著一個(gè)扎眼的 Uncaught (in promise)。

這究竟是為什么?難道 try...catch 對(duì) Promise 無(wú)效嗎?

別急,這并非 try...catch 的 bug,而是我們對(duì) 同步 與 異步 的理解出了偏差。

核心原因:try...catch 是同步的,而 Promise 是異步的

讓我們用一個(gè)更簡(jiǎn)單的比喻來(lái)理解:

你點(diǎn)了一份外賣(mài)(發(fā)起一個(gè) Promise 請(qǐng)求)。try...catch 就像你家門(mén)口的保安。

  • 你下單的動(dòng)作是瞬間完成的。你按下“支付”按鈕,App 立刻告訴你“下單成功,騎手正在路上”。這個(gè)“下單成功”的反饋是 同步 的。
  • 保安 try...catch 只在你下單的那個(gè)瞬間盯著你。他看到你成功下了單,沒(méi)出任何問(wèn)題(比如網(wǎng)絡(luò)斷了、余額不足等),于是他就下班了。
  • 半小時(shí)后,騎手送餐路上翻車(chē)了(Promise 狀態(tài)變?yōu)?rejected)。這個(gè)錯(cuò)誤發(fā)生在未來(lái),發(fā)生在保安下班之后。保安自然是抓不到這個(gè)“錯(cuò)誤”的。

回到代碼中:

  • try { ... } 塊里的代碼是 同步執(zhí)行 的。
  • fetch(...) 這個(gè)函數(shù)被調(diào)用時(shí),它 立即返回 一個(gè) Promise 對(duì)象。在 try 塊看來(lái),這個(gè)返回動(dòng)作是成功的,沒(méi)有任何錯(cuò)誤被“拋出”(throw)。
  • 所以,try 塊順利執(zhí)行完畢,catch 自然不會(huì)被觸發(fā)。
  • 真正的網(wǎng)絡(luò)錯(cuò)誤發(fā)生在稍后的某個(gè)時(shí)間點(diǎn),當(dāng)這個(gè)錯(cuò)誤發(fā)生時(shí),它改變了那個(gè)已經(jīng)返回的 Promise 對(duì)象的狀態(tài),將其置為 rejected。這個(gè)錯(cuò)誤屬于 異步世界,而同步的 try...catch早已執(zhí)行完畢,鞭長(zhǎng)莫及。

正確的姿勢(shì):使用 async/await

那么,如何讓保安(try...catch)等到外賣(mài)送到(或出事)再下班呢?答案就是使用 async/await。

await 關(guān)鍵字有一個(gè)神奇的魔力:它會(huì)“暫停”當(dāng)前 async 函數(shù)的執(zhí)行,直到它等待的 Promise 有了結(jié)果(無(wú)論是成功 resolved 還是失敗 rejected)。

如果 Promise 失敗了,await 會(huì)像一個(gè)“信使”,把這個(gè)異步的錯(cuò)誤“解包”并 重新在當(dāng)前同步上下文中拋出。這樣一來(lái),try...catch 就能穩(wěn)穩(wěn)地接住它了。

讓我們來(lái)改造一下代碼:

看,這次 catch 完美地捕獲了錯(cuò)誤!

async/await 的工作流程:

  • 函數(shù)用 async 標(biāo)記,表示這是一個(gè)異步函數(shù)。
  • await 守在 fetch(...) 前面,函數(shù)執(zhí)行到這里就“暫?!绷耍粫?huì)阻塞整個(gè)程序。
  • 它耐心等待 fetch 返回的 Promise 結(jié)果。
  • 當(dāng) Promise 因?yàn)榫W(wǎng)絡(luò)問(wèn)題而 rejected 時(shí),await 將這個(gè) rejection 的原因(也就是那個(gè) error 對(duì)象)作為一個(gè)同步錯(cuò)誤 throw 出來(lái)。
  • 這個(gè)被 throw 出來(lái)的錯(cuò)誤,正好在 try 塊的作用域內(nèi),于是被 catch 成功捕獲。

別忘了還有 .catch() 方法

當(dāng)然,處理 Promise 錯(cuò)誤并非只有 async/await 這一條路。在 async/await 出現(xiàn)之前,我們一直使用 Promise 自帶的 .catch() 方法鏈?zhǔn)秸{(diào)用來(lái)處理錯(cuò)誤,這同樣非常有效。

fetch('https://non-existent-url.com/api')
  .then(response => {
    if (!response.ok) {
      // 手動(dòng)拋出一個(gè)錯(cuò)誤,讓下面的 .catch() 捕獲
      throw new Error('網(wǎng)絡(luò)響應(yīng)不佳');
    }
    return response.json();
  })
  .then(data => {
    console.log('請(qǐng)求成功:', data);
  })
  .catch(error => {
    // 任何在 .then() 鏈中發(fā)生的錯(cuò)誤都會(huì)在這里被捕獲
    console.log('在 .catch() 方法中抓到錯(cuò)誤了!', error);
  });

這種方式的優(yōu)點(diǎn)是代碼結(jié)構(gòu)清晰,形成了一條“成功路徑” (.then) 和一條“失敗路徑” (.catch)。

責(zé)任編輯:趙寧寧 來(lái)源: JavaScript
相關(guān)推薦

2020-06-30 08:12:32

VMwareKVMDocker

2022-08-15 08:01:00

三色標(biāo)記JVM算法

2021-07-29 16:56:59

微信騰訊注冊(cè)

2025-04-03 10:39:56

2022-10-21 08:17:13

MongoDB查詢(xún)Document

2018-06-04 08:40:20

磁盤(pán)分區(qū)MBR

2021-02-07 08:13:18

@DateTimeFo@NumberFormSpring

2020-03-04 08:47:10

Kafka架構(gòu)原理

2020-02-23 15:55:00

疫情AI人工智能

2020-11-12 07:32:53

JavaScript

2022-01-14 14:19:38

ReactTS前端

2012-01-11 09:15:45

Objective-C

2025-06-25 08:15:00

JavaScrip異步編程代碼

2020-09-27 07:48:40

不用try catch

2024-10-11 11:59:03

2017-06-06 15:13:07

2022-12-14 07:32:40

InnoDBMySQL引擎

2023-09-07 07:53:21

JavaScriptGoRust

2023-04-09 23:25:30

Java注解元注解

2018-04-02 15:13:21

網(wǎng)絡(luò)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)