# Vue.js如何防止重復請求
## 引言
在前端開發中,重復請求是一個常見但容易被忽視的問題。當用戶頻繁點擊按鈕或網絡延遲較高時,可能導致同一請求被多次發送,不僅浪費服務器資源,還可能引發數據一致性問題。本文將深入探討在Vue.js項目中防止重復請求的多種解決方案。
---
## 一、為什么需要防止重復請求?
### 1. 性能影響
- 不必要的網絡請求消耗帶寬
- 增加服務器壓力
### 2. 數據一致性風險
- 并發請求可能導致競態條件
- 后發請求可能覆蓋先發請求的結果
### 3. 用戶體驗問題
- 重復提交可能導致界面狀態混亂
- 用戶可能因延遲重復操作
---
## 二、基礎解決方案
### 1. 按鈕禁用(UI層控制)
```vue
<template>
<button :disabled="isLoading" @click="submit">
{{ isLoading ? '提交中...' : '提交' }}
</button>
</template>
<script>
export default {
data() {
return {
isLoading: false
}
},
methods: {
async submit() {
if (this.isLoading) return
this.isLoading = true
try {
await axios.post('/api/submit', data)
} finally {
this.isLoading = false
}
}
}
}
</script>
優缺點: - ? 實現簡單直觀 - ? 無法防止編程式多次調用
let pendingRequest = null
async function fetchData() {
if (pendingRequest) {
return pendingRequest
}
pendingRequest = axios.get('/api/data')
try {
return await pendingRequest
} finally {
pendingRequest = null
}
}
// 請求緩存Map
const pendingMap = new Map()
axios.interceptors.request.use(config => {
const key = `${config.method}-${config.url}`
if (pendingMap.has(key)) {
return Promise.reject(new Error('重復請求'))
}
pendingMap.set(key, true)
config.cancelToken = new axios.CancelToken(cancel => {
config.cancel = cancel
})
return config
})
axios.interceptors.response.use(
response => {
const key = `${response.config.method}-${response.config.url}`
pendingMap.delete(key)
return response
},
error => {
if (!axios.isCancel(error)) {
const key = `${error.config.method}-${error.config.url}`
pendingMap.delete(key)
}
return Promise.reject(error)
}
)
// store/modules/request.js
export default {
state: {
pendingRequests: {}
},
mutations: {
setPending(state, { key, status }) {
Vue.set(state.pendingRequests, key, status)
}
},
actions: {
async makeRequest({ state, commit }, { key, requestFn }) {
if (state.pendingRequests[key]) {
throw new Error('請求已在進行中')
}
commit('setPending', { key, status: true })
try {
return await requestFn()
} finally {
commit('setPending', { key, status: false })
}
}
}
}
// 在組件中使用
export default {
data() {
return {
cancelToken: null
}
},
methods: {
fetchData() {
this.cancelToken = axios.CancelToken.source()
axios.get('/api/data', {
cancelToken: this.cancelToken.token
})
}
},
beforeRouteLeave(to, from, next) {
if (this.cancelToken) {
this.cancelToken.cancel('路由跳轉取消請求')
}
next()
}
}
import { debounce } from 'lodash'
export default {
methods: {
search: debounce(async function(query) {
try {
const res = await axios.get('/api/search', { params: { q: query } })
// 處理結果
} catch (error) {
// 錯誤處理
}
}, 500)
}
}
分層防御:
錯誤處理:
性能權衡:
TypeScript增強:
interface ExtendedAxiosConfig extends AxiosRequestConfig {
_retryCount?: number
_isPending?: boolean
}
防止重復請求是提升Vue.js應用健壯性的重要環節。開發者應根據實際場景選擇合適的方案組合,在用戶體驗和系統穩定性之間取得平衡。隨著Vue 3的Composition API普及,我們還可以將這些邏輯封裝為可復用的組合式函數,進一步提高代碼的可維護性。 “`
(全文約1050字)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。