前端JS 異常處理實踐
前端異常處理,常見的場景是在“異步請求”的操作過程當中,所謂“異常”---就是“不正常”,程序的運行不符合我們的預期。
程序“正常”的處理,是我們在開發過程當中的“重中之重”,是必要的“硬性指標”。
而“異常處理”,很多時候可能連“指標”都沒有,更談不上什麽“硬性指標”了,所以,在開發當中是很容易被忽略的一個“主題”。
但是,“提高用戶體驗”與“提高程序可控性”又是兩個永恒的主題,“枝繁葉茂”就是我們追求的目標(枝---主功能;葉---細節;)。
在追求“枝繁葉茂”的過程當中,“異常處理”就是細節當中的重中之重,故此,對此進行了如下實踐:
常見的“異步請求”操作:1.ajax(以$.ajax為例);2.fetch;
此處對這兩種方式的“異常處理”進行了實踐(包括try,catch,finally,throw error,new Error(),console.error的運用),以fetch實踐為主,由於fetch返回的實際上是promise對象,為了方便查看測試效果,此處直接使用promise對象代替說明。
一.$.ajax相關
$.ajax({ url: "/hello?name=平凡視界", type: "GET", success: (data) =>{ //成功相關處理 console.log(‘返回數據‘,data) }, error: (err)=>{ //錯誤相關處理 404屬於該處理(經測試) //還可能是"timeout", "error", "notmodified" 和 "parsererror"。 console.log(‘錯誤處理‘,err); } });
二.fetch相關
實踐1:當程序運行遇到 throw error 時,JS引擎會停止後續業務執行,程序直接進入catch環節;
new Promise((res, rej) =>{ console.log(‘異步開始。。。‘); setTimeout(() =>{ const error = new Error(‘粗錯啦~‘);throw error; //JS引擎會停止後續業務執行,程序直接進入catch環節 res(‘異步OK‘); },3000) }) .then((data) =>{ console.log(‘異步執行OK‘,data);//並沒有執行 },(data) =>{ console.log(‘異步執行拒絕‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘二次then執行OK‘,data);//並沒有執行 }) .catch((err) =>{ console.error(‘嘿‘,err);//執行OK })
實踐2:當程序 resolve 時,在後續then操作當中註冊的resolve handle會順次執行,註冊的reject handle與catch並未執行;
new Promise((res, rej) =>{ console.log(‘異步開始。。。‘); setTimeout(() =>{ res(‘異步OK‘); },3000) }) .then((data) =>{ console.log(‘異步執行OK‘,data);//執行OK },(data) =>{ console.log(‘異步執行拒絕‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘二次then執行OK‘,data);//執行OK }) .catch((err) =>{ console.error(‘嘿‘,err);//並沒有執行 })
實踐3:當程序 reject 時,在後續“子1級”then操作當中註冊的reject handle執行---驗證1,其他註冊的resolve handle與catch並未執行;
new Promise((res, rej) =>{ console.log(‘異步開始。。。‘); setTimeout(() =>{ rej(‘異步失敗‘); },3000) }) .then((data) =>{ console.log(‘異步執行OK‘,data);//並沒有執行 },(data) =>{ console.log(‘異步執行拒絕‘,data);//執行OK }) .then((data) =>{ console.log(‘二次then執行OK‘,data);//執行OK }) .catch((err) =>{ console.error(‘嘿‘,err);//並沒有執行 })
實踐4:當程序 reject 時,在後續“子2級”then操作當中註冊的reject handle執行---驗證2(子1級中,並沒有註冊reject handle相關的處理機制,故被在“子2級”then操作當中註冊的reject handle接收,並執行處理),其他註冊的resolve handle與catch並未執行;
new Promise((res, rej) =>{ console.log(‘異步開始。。。‘); setTimeout(() =>{ rej(‘異步失敗‘); },3000) }) .then((data) =>{ console.log(‘異步執行OK‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘二次then執行OK‘,data);//並沒有執行 },(data) =>{ console.log(‘二次then"接收"reject異步"執行結果"(拒絕)‘,data);//執行OK }) .catch((err) =>{ console.error(‘嘿‘,err);//並沒有執行 })
實踐5:當程序 reject 時,在後續“子4級”then操作當中註冊的reject handle執行---驗證2(“子1級”至“子3級”中,並沒有註冊reject handle相關的處理機制,故被在“子4級”then操作當中註冊的reject handle接收,並執行處理),其他註冊的resolve handle與catch並未執行;
new Promise((res, rej) =>{ console.log(‘異步開始。。。‘); setTimeout(() =>{ rej(‘異步失敗‘); },3000) }) .then((data) =>{ console.log(‘異步執行OK1‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘異步執行OK2‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘異步執行OK3‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘二次then執行OK4‘,data);//並沒有執行 },(data) =>{ console.log(‘二次then"接收"reject異步"執行結果"(拒絕)‘,data);//執行OK }) .catch((err) =>{ console.error(‘嘿‘,err);//並沒有執行 })
實踐6:當程序 reject 時,“子1級”至“子4級”中,並沒有註冊reject handle相關的處理機制,故被catch接收,並執行處理,其他註冊的resolve handle並未執行;
new Promise((res, rej) =>{ console.log(‘異步開始。。。‘); setTimeout(() =>{ rej(‘異步失敗‘); },3000) }) .then((data) =>{ console.log(‘異步執行OK1‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘異步執行OK2‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘異步執行OK3‘,data);//並沒有執行 }) .then((data) =>{ console.log(‘異步執行OK4‘,data);//並沒有執行 }) .catch((err) =>{ console.error(‘嘿‘,err);//執行OK-----rej的時候,“其後程序”沒有對rejct進行相應處理時, //catch會接收該reject響應,並進行處理 })
三.try,catch,finally,throw error,new Error(),console.error的運用;
try{ console.log("test"); throw new Error(‘出錯了吧?‘);//throw 後面的參數,會被catch中的e接收 } catch(e){ // e == ‘出錯了吧?‘ console.error(e);// 出錯了吧? } finally{ console.log(‘怎麽都會執行‘);// 執行OK }
四.總結
1.當程序執行遇到“throw error”時,JS引擎會停止後續業務執行,程序直接進入catch環節; (promise對象,try包裹的代碼塊) 2.promise: --- resolve: 大多時候(除:網絡故障與請求被阻止外),使用fetch()返回的 Promise被標記為resolve, 包括(接收到一個代表錯誤的 HTTP 狀態碼時,HTTP 響應的狀態碼是 404 或 500,但是,此時會將 resolve 的返回值的 ok 屬性設置為 false, 如果需要進行細分,可以根據該屬性進行細分---在“異步請求”中,處理的大多數異常或error針對該階段異常) --- reject: 使用fetch()返回的 Promise被標記為 reject的情況僅有兩種(1.網絡故障;2.請求被阻止(如“跨域”))說明:當程序在reject時,如果後續沒有註冊“相關程序”來接收處理,那麽,該reject會被catch處理,在該reject發生之後註冊的一切reslove 業務將不會被執行; 當程序在reject時,如果後續有註冊“相關程序”來接收處理,那麽,該reject會被所“註冊”的函數進行處理,在該註冊函數之後的一切reslove 業務不會受該reject的影響,會依次執行,同時,catch不會被“該reject”觸發; 3.try catch finally:
try{ #1運行代碼 } catch(err){ #1出錯,程序直接進入該環節 } finally{ #1出錯 or 正常,程序都進入該環節 }
前端JS 異常處理實踐