相信我們經常這樣寫 bug(不是 👇:
try {
const res = await api.getUser()
console.log('✅ 使用者資訊', res)
} catch (err) {
console.error('❌ 請求失敗', err)
}
看似沒問題
💡 目標:不拋異常的安全請求封裝
我們希望實現這樣的調用👇:
const [err, data] = await safeRequest(api.getUser(1))
if (err) return showError(err)
console.log('✅ 使用者資訊:', data)
是不是清爽多了?✨
沒有 try-catch,卻能同時拿到錯誤和數據。
// src/utils/request.js
import axios from 'axios'
import { ElMessage } from 'element-plus'
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000,
})
// 🧱 請求攔截器
service.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token')
if (token) config.headers.Authorization = `Bearer ${token}`
return config
},
(error) => Promise.reject(error)
)
// 🧱 回應攔截器
service.interceptors.response.use(
(response) => {
const res = response.data
if (res.code !== 0) {
ElMessage.error(res.message || '請求失敗')
return Promise.reject(new Error(res.message || '請求失敗'))
}
return res.data
},
(error) => {
ElMessage.error(error.message || '網路錯誤')
return Promise.reject(error)
}
)
export default service
攔截器的作用:
// src/utils/safeRequest.js
export async function safeRequest(promise) {
try {
const data = await promise
return [null, data] // ✅ 成功時返回 [null, data]
} catch (err) {
return [err, null] // ❌ 失敗時返回 [err, null]
}
}
這就是關鍵!
它讓所有 Promise 都變得「溫柔」——不再拋出異常,而是返回結構化結果。
// src/api/user.js
import request from '@/utils/request'
export const userApi = {
getUser(id) {
return request.get(`/user/${id}`)
},
updateUser(data) {
return request.put('/user', data)
},
}
<script setup>
import { ref, onMounted } from 'vue'
import { userApi } from '@/api/user'
import { safeRequest } from '@/utils/safeRequest'
const user = ref(null)
onMounted(async () => {
const [err, data] = await safeRequest(userApi.getUser(1))
if (err) return showError(err)
console.log('✅ 使用者資訊:', data)
})
</script>
是不是很優雅、數據邏輯清晰、不需要 try-catch、 錯誤不崩潰。
老闆說:牛🍺,你小子有點東西
我們可以給 safeRequest 增加一個選項,讓錯誤自動提示:
// src/utils/safeRequest.js
import { ElMessage } from 'element-plus'
export async function safeRequest(promise, { showError = true } = {}) {
try {
const data = await promise
return [null, data]
} catch (err) {
if (showError) {
ElMessage.error(err.message || '請求失敗')
}
return [err, null]
}
}
使用時👇:
const [err, data] = await safeRequest(userApi.getUser(1), { showError: false })
這樣你可以靈活控制是否彈出錯誤提示,
比如某些靜默請求就可以關閉提示。
如果你用的是 TypeScript,可以讓返回類型更智能👇:
export async function safeRequest<T>(
promise: Promise<T>
): Promise<[Error | null, T | null]> {
try {
const data = await promise
return [null, data]
} catch (err) {
return [err as Error, null]
}
}
調用時:
const [err, user] = await safeRequest<User>(userApi.getUser(1))
if (user) console.log(user.name) // ✅ 自動提示類型
老闆:寫得很好,下次多寫點,明天你來當老闆