try catch 在實際開發(fā)場景中的五大用處,用起來!??!
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點(diǎn)是我的座右銘,基礎(chǔ)是進(jìn)階的前提是我的初心~
昨天一位群友在面試的時候被問到了這么一個問題:多個請求同時發(fā)起時,如何保證失敗或者成功都返回,我第一啥時間就想到了 Promise.allSettled
來實現(xiàn)
// 模擬多個異步操作:獲取用戶基本信息、訂單記錄、消息通知
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('請求超時')), 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: 請求超時
*/
但是他說了:面試官說除了 Promise.allSettled 實現(xiàn),還有什么其他辦法嗎? 于是我又想到了使用 try catch + Promise.all
:
// 模擬多個異步操作:獲取用戶基本信息、訂單記錄、消息通知
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('請求超時')), 3000)
)
} catch {
returnnull
}
}
// 使用 Promise.all
Promise.all([
fetchUserInfo(),
fetchOrders(),
fetchNotifications()
]).then(res => {
console.log(res)
// [
// {id: 1, name: "張三"},
// [ {...}, {...} ],
// null
// ]
})
接著這位群友問我能不能出一篇 try catch
在實際開發(fā)中的使用場景,我想想其實可以講講
try catch 場景
1、異步請求的優(yōu)雅處理
典型場景: 處理 AJAX/Fetch 請求時網(wǎng)絡(luò)錯誤、接口異常
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('請求失敗:', error);
showToast('數(shù)據(jù)加載失敗,請檢查網(wǎng)絡(luò)');
// 降級處理:顯示緩存數(shù)據(jù)/缺省頁面
}
}
2、JSON 解析的安全防護(hù)
常見問題: JSON.parse()
遇到非法格式時導(dǎo)致整個應(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、第三方庫的錯誤隔離
痛點(diǎn)場景: 不確定穩(wěn)定性的插件/工具庫可能拋出意外錯誤
function safePluginInit() {
try {
ThirdPartyPlugin.init({
// 復(fù)雜配置項
});
} catch (e) {
captureErrorToSentry(e); // 上報錯誤
loadFallbackPlugin(); // 降級方案
}
}
4、表單驗證的靈活應(yīng)用
function validateForm(formData) {
try {
if (!formData.email.includes('@')) {
thrownew ValidationError('郵箱格式錯誤');
}
if (formData.password.length < 8) {
thrownew ValidationError('密碼至少8位');
}
} catch (e) {
if (e instanceof ValidationError) {
highlightErrorField(e.message);
returnfalse;
}
// 其他未知錯誤繼續(xù)拋出
throw e;
}
}
5、瀏覽器特性檢測的優(yōu)雅降級
兼容性處理: 替代傳統(tǒng)的特性檢測寫法
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();
}