国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 語(yǔ)言 > JavaScript > 正文

JS異步錯(cuò)誤捕獲的一些事小結(jié)

2024-05-06 15:40:07
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

引入

我們都知道 try catch 無(wú)法捕獲 setTimeout 異步任務(wù)中的錯(cuò)誤,那其中的原因是什么。以及異步代碼在 js 中是特別常見(jiàn)的,我們?cè)撛趺醋霾疟容^?

無(wú)法捕獲的情況

function main() { try { setTimeout(() => { throw new Error('async error') }, 1000) } catch(e) { console.log(e, 'err') console.log('continue...') }}main();

這段代碼中,setTimeout 的回調(diào)函數(shù)拋出一個(gè)錯(cuò)誤,并不會(huì)在 catch 中捕獲,會(huì)導(dǎo)致程序直接報(bào)錯(cuò)崩掉。

所以說(shuō)在 js 中 try catch 并不是說(shuō)寫(xiě)上一個(gè)就可以高枕無(wú)憂了。難道每個(gè)函數(shù)都要寫(xiě)嗎,
那什么情況下 try catch 無(wú)法捕獲 error 呢?

異步任務(wù)

宏任務(wù)的回調(diào)函數(shù)中的錯(cuò)誤無(wú)法捕獲

上面的栗子稍微改一下,主任務(wù)中寫(xiě)一段 try catch,然后調(diào)用異步任務(wù) task,task 會(huì)在一秒之后拋出一個(gè)錯(cuò)誤。

// 異步任務(wù)const task = () => { setTimeout(() => { throw new Error('async error') }, 1000)}// 主任務(wù)function main() { try { task(); } catch(e) { console.log(e, 'err') console.log('continue...') }}

這種情況下 main 是無(wú)法 catch error 的,這跟瀏覽器的執(zhí)行機(jī)制有關(guān)。異步任務(wù)由 eventloop 加入任務(wù)隊(duì)列,并取出入棧(js 主進(jìn)程)執(zhí)行,而當(dāng) task 取出執(zhí)行的時(shí)候, main 的棧已經(jīng)退出了,也就是上下文環(huán)境已經(jīng)改變,所以 main 無(wú)法捕獲 task 的錯(cuò)誤。

事件回調(diào),請(qǐng)求回調(diào)同屬 tasks,所以道理是一樣的。eventloop 復(fù)習(xí)可以看這篇文章

微任務(wù)(promise)的回調(diào)
// 返回一個(gè) promise 對(duì)象const promiseFetch = () =>  new Promise((reslove) => { reslove();})function main() { try { // 回調(diào)函數(shù)里拋出錯(cuò)誤 promiseFetch().then(() => { throw new Error('err') }) } catch(e) { console.log(e, 'eeee'); console.log('continue'); }}

promise 的任務(wù),也就是 then 里面的回調(diào)函數(shù),拋出錯(cuò)誤同樣也無(wú)法 catch。因?yàn)槲⑷蝿?wù)隊(duì)列是在兩個(gè) task 之間清空的,所以 then 入棧的時(shí)候,main 函數(shù)也已經(jīng)出棧了。

并不是回調(diào)函數(shù)無(wú)法 try catch

很多人可能有一個(gè)誤解,因?yàn)榇蟛糠钟龅綗o(wú)法 catch 的情況,都發(fā)生在回調(diào)函數(shù),就認(rèn)為回調(diào)函數(shù)不能 catch。

不全對(duì),看一個(gè)最普通的栗子。

// 定義一個(gè) fn,參數(shù)是函數(shù)。const fn = (cb: () => void) => { cb();};function main() { try { // 傳入 callback,fn 執(zhí)行會(huì)調(diào)用,并拋出錯(cuò)誤。 fn(() => { throw new Error('123'); }) } catch(e) { console.log('error'); }}main();

結(jié)果當(dāng)然是可以 catch 的。因?yàn)?callback 執(zhí)行的時(shí)候,跟 main 還在同一次事件循環(huán)中,即一個(gè) eventloop tick。所以上下文沒(méi)有變化,錯(cuò)誤是可以 catch 的。

根本原因還是同步代碼,并沒(méi)有遇到異步任務(wù)。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 河北区| 六安市| 芦溪县| 黄冈市| 华宁县| 三明市| 公安县| 富蕴县| 安义县| 高安市| 炉霍县| 安塞县| 榆林市| 湖南省| 山东省| 历史| 田阳县| 丹阳市| 庆阳市| 古田县| 曲松县| 方山县| 新田县| 朝阳县| 吉安县| 磐石市| 永济市| 广汉市| 顺昌县| 会同县| 璧山县| 积石山| 吴忠市| 东乡族自治县| 兴文县| 胶南市| 西昌市| 昌都县| 报价| 孙吴县| 梨树县|