相信我们经常这样写bug(不是 👇:

js
try {
const res = await api.getUser()
console.log('✅ 用户信息', res)
} catch (err) {
console.error('❌ 请求失败', err)
}
看似没问题
- 每个接口都要 try-catch,太啰嗦了!
- 错误处理逻辑分散,不可控!
- 代码又臭又长💨!
💡 目标:不抛异常的安全请求封装
我们希望实现这样的调用👇:
js
const [err, data] = await safeRequest(api.getUser(1))
if (err) {
console.warn('❌ 获取用户失败:', err.message)
} else {
console.log('✅ 用户信息:', data)
}
是不是清爽多了?✨
没有 try-catch,却能同时拿到错误和数据。
🧩 实现步骤
1️⃣ 先封装 Axios 实例
js
// 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
拦截器的作用:
- ✅ 统一处理 token;
- ✅ 统一处理错误提示;
- ✅ 保证业务层拿到的永远是"干净的数据"。
2️⃣ 封装一个「安全请求函数」
js
// 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 都变得「温柔」------不再抛出异常,而是返回结构化结果。
3️⃣ 封装 API 模块
js
// 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)
},
}
4️⃣ 在业务层优雅调用
vue
<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) {
console.warn('❌ 获取用户失败:', err.message)
} else {
user.value = data
}
})
</script>
是不是很优雅、数据逻辑清晰、不需要 try-catch、 错误不崩溃。
老板说:牛🍺,你小子有点东西
🧱 我们还可以进一步优化:实现自动错误提示
我们可以给 safeRequest 增加一个选项,让错误自动提示:
js
// 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]
}
}
使用时👇:
js
const [err, data] = await safeRequest(userApi.getUser(1), { showError: false })
这样你可以灵活控制是否弹出错误提示,
比如某些静默请求就可以关闭提示。
🧠 进阶:TypeScript 支持(超丝滑)
如果你用的是 TypeScript,可以让返回类型更智能👇:
ts
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]
}
}
调用时:
ts
const [err, user] = await safeRequest<User>(userApi.getUser(1))
if (user) console.log(user.name) // ✅ 自动提示类型
老板:写得很好,下次多写点,明天你来当老板

有27届前端仔要实习的可以来看看广州双休小工厂:juejin.cn/post/756520...

