我删光了项目里的 try-catch,老板:6
相信我们经常这样写bug(不是 👇:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(linetry {const res = await api.getUser()console.log('✅ 用户信息', res)} catch (err) {console.error('❌ 请求失败', err)}
看似没问题
每个接口都要 try-catch,太啰嗦了! 错误处理逻辑分散,不可控! 代码又臭又长💨!
💡 目标:「不抛异常的安全请求封装」
我们希望实现这样的调用👇:
ounter(lineounter(lineounter(lineounter(lineconst [err, data] = await safeRequest(api.getUser(1))if (err) return showError(err)console.log('✅ 用户信息:', data)
是不是清爽多了?✨
没有 try-catch,却能同时拿到错误和数据。
🧩 实现步骤
1️⃣ 先封装 Axios 实例
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line// src/utils/request.jsimport 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.dataif (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
拦截器的作用:
✅ 统一处理 token; ✅ 统一处理错误提示; ✅ 保证业务层拿到的永远是“干净的数据”。
2️⃣ 封装一个「安全请求函数」
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line// src/utils/safeRequest.jsexport async function safeRequest(promise) {try {const data = await promisereturn [null, data] // ✅ 成功时返回 [null, data]} catch (err) {return [err, null] // ❌ 失败时返回 [err, null]}}
这就是关键!
它让所有 Promise 都变得「温柔」——不再抛出异常,而是返回结构化结果。
3️⃣ 封装 API 模块
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line// src/api/user.jsimport request from '@/utils/request'export const userApi = {getUser(id) {return request.get(`/user/${id}`)},updateUser(data) {return request.put('/user', data)},}
4️⃣ 在业务层优雅调用
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line<scriptsetup>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 增加一个选项,让错误自动提示:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line// src/utils/safeRequest.jsimport { ElMessage } from 'element-plus'export async function safeRequest(promise, { showError = true } = {}) {try {const data = await promisereturn [null, data]} catch (err) {if (showError) {ElMessage.error(err.message || '请求失败')}return [err, null]}}
使用时👇:
ounter(lineconst [err, data] = await safeRequest(userApi.getUser(1), { showError: false })
这样你可以灵活控制是否弹出错误提示,
比如某些静默请求就可以关闭提示。
🧠 进阶:TypeScript 支持(超丝滑)
如果你用的是 TypeScript,可以让返回类型更智能👇:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineexport async function safeRequest<T>(promise: Promise<T>): Promise<[Error | null, T | null]> {try {const data = await promisereturn [null, data]} catch (err) {return [err as Error, null]}}
调用时:
ounter(lineounter(lineconst [err, user] = await safeRequest<User>(userApi.getUser(1))if (user) console.log(user.name) // ✅ 自动提示类型
老板:写得很好,下次多写点,明天你来当老板!