try catch 在實(shí)際開(kāi)發(fā)場(chǎng)景中的五大用處,用起來(lái)?。。?/h1>
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識(shí)點(diǎn)是我的座右銘,基礎(chǔ)是進(jìn)階的前提是我的初心~
昨天一位群友在面試的時(shí)候被問(wèn)到了這么一個(gè)問(wèn)題:多個(gè)請(qǐng)求同時(shí)發(fā)起時(shí),如何保證失敗或者成功都返回,我第一啥時(shí)間就想到了 Promise.allSettled
來(lái)實(shí)現(xiàn)
// 模擬多個(gè)異步操作:獲取用戶基本信息、訂單記錄、消息通知
const fetchUserInfo = () =>
fetch('/api/user').then(res => res.json());
const fetchOrders = () =>
fetch('/api/orders').then(res => {
if (!res.ok) thrownewError('訂單獲取失敗')
return res.json()
});
const fetchNotifications = () =>
newPromise((_, reject) =>
setTimeout(() => reject(newError('請(qǐng)求超時(shí)')), 3000)
);
// 使用 Promise.allSettled 并行執(zhí)行
Promise.allSettled([
fetchUserInfo(),
fetchOrders(),
fetchNotifications()
])
.then(results => {
const [userResult, ordersResult, notifyResult] = results;
// 處理用戶信息
if (userResult.status === 'fulfilled') {
console.log('用戶數(shù)據(jù):', userResult.value);
renderUserProfile(userResult.value);
} else {
console.error('用戶信息失敗:', userResult.reason);
showPlaceholder('#user-section');
}
// 處理訂單數(shù)據(jù)
if (ordersResult.status === 'fulfilled') {
console.log('訂單數(shù)據(jù):', ordersResult.value);
renderOrderList(ordersResult.value);
} else {
console.error('訂單獲取失敗:', ordersResult.reason);
showErrorToast('訂單加載異常');
}
// 處理通知數(shù)據(jù)
if (notifyResult.status === 'fulfilled') {
console.log('通知數(shù)據(jù):', notifyResult.value);
updateNotificationBadge(notifyResult.value);
} else {
console.warn('通知獲取失敗:', notifyResult.reason);
disableNotificationBell();
}
});
/* 輸出示例:
用戶數(shù)據(jù): {id: 1, name: "張三"}
訂單數(shù)據(jù): [ {...}, {...} ]
通知獲取失敗: Error: 請(qǐng)求超時(shí)
*/
但是他說(shuō)了:面試官說(shuō)除了 Promise.allSettled 實(shí)現(xiàn),還有什么其他辦法嗎? 于是我又想到了使用 try catch + Promise.all
:
// 模擬多個(gè)異步操作:獲取用戶基本信息、訂單記錄、消息通知
const fetchUserInfo = async () => {
try {
const res = await fetch('/api/user')
return res.json()
} catch {
returnnull
}
}
const fetchOrders = async () => {
try {
const res = await fetch('/api/orders')
if (!res.ok) thrownewError('訂單獲取失敗')
return res.json()
} catch {
returnnull
}
}
const fetchNotifications = async () => {
try {
awaitnewPromise((_, reject) =>
setTimeout(() => reject(newError('請(qǐng)求超時(shí)')), 3000)
)
} catch {
returnnull
}
}
// 使用 Promise.all
Promise.all([
fetchUserInfo(),
fetchOrders(),
fetchNotifications()
]).then(res => {
console.log(res)
// [
// {id: 1, name: "張三"},
// [ {...}, {...} ],
// null
// ]
})
接著這位群友問(wèn)我能不能出一篇 try catch
在實(shí)際開(kāi)發(fā)中的使用場(chǎng)景,我想想其實(shí)可以講講
try catch 場(chǎng)景
1、異步請(qǐng)求的優(yōu)雅處理
典型場(chǎng)景: 處理 AJAX/Fetch 請(qǐng)求時(shí)網(wǎng)絡(luò)錯(cuò)誤、接口異常
async function fetchUserData() {
try {
const response = await fetch('/api/user');
if (!response.ok) thrownewError('HTTP Error');
const data = await response.json();
// 正常處理邏輯
} catch (error) {
console.error('請(qǐng)求失敗:', error);
showToast('數(shù)據(jù)加載失敗,請(qǐng)檢查網(wǎng)絡(luò)');
// 降級(jí)處理:顯示緩存數(shù)據(jù)/缺省頁(yè)面
}
}
2、JSON 解析的安全防護(hù)
常見(jiàn)問(wèn)題: JSON.parse()
遇到非法格式時(shí)導(dǎo)致整個(gè)應(yīng)用崩潰
function safeParse(jsonString) {
try {
return JSON.parse(jsonString);
} catch (e) {
console.warn('JSON 解析失敗,返回默認(rèn)值');
return {}; // 或執(zhí)行其他恢復(fù)邏輯
}
}
// 使用案例
const userPrefs = safeParse(localStorage.getItem('preferences'));
3、第三方庫(kù)的錯(cuò)誤隔離
痛點(diǎn)場(chǎng)景: 不確定穩(wěn)定性的插件/工具庫(kù)可能拋出意外錯(cuò)誤
function safePluginInit() {
try {
ThirdPartyPlugin.init({
// 復(fù)雜配置項(xiàng)
});
} catch (e) {
captureErrorToSentry(e); // 上報(bào)錯(cuò)誤
loadFallbackPlugin(); // 降級(jí)方案
}
}
4、表單驗(yàn)證的靈活應(yīng)用
function validateForm(formData) {
try {
if (!formData.email.includes('@')) {
thrownew ValidationError('郵箱格式錯(cuò)誤');
}
if (formData.password.length < 8) {
thrownew ValidationError('密碼至少8位');
}
} catch (e) {
if (e instanceof ValidationError) {
highlightErrorField(e.message);
returnfalse;
}
// 其他未知錯(cuò)誤繼續(xù)拋出
throw e;
}
}
5、瀏覽器特性檢測(cè)的優(yōu)雅降級(jí)
兼容性處理: 替代傳統(tǒng)的特性檢測(cè)寫(xiě)法
function checkWebGLSupport() {
try {
const canvas = document.createElement('canvas');
return !!window.WebGLRenderingContext &&
(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
} catch (e) {
returnfalse;
}
}
if (!checkWebGLSupport()) {
showCompatibilityWarning();
load2DFallback();
}