大家好,我是大澈!
本文約?1400+ ?字,整篇閱讀約需?3?分鐘。
防止接口重復請求在軟件開發中非常重要,重復請求必然會導致服務器資源的浪費。
因為每次請求都需要服務器進行處理,如果請求是重復的,那么服務器就在做不必要的工作。在高并發的場景下,這種浪費會成倍增加,可能導致服務器性能下降,甚至引發服務崩潰。
所以,今天我們一起來聊一聊,如何防止接口重復請求?
七種實現方式
1、?請求隊列:維護一個請求隊列,每次發送請求前檢查隊列中是否已經存在相同的請求。如果存在相同請求,則不再發送,直接使用隊列中的請求結果。這種方法可以確保相同請求只發送一次。
class?RequestQueue?{??constructor()?{??this.queue?=?{};??}??addRequest(url,?callback)?{??if?(this.queue[url])?{??//?如果隊列中已有相同請求,則直接使用之前的請求結果??this.queue[url].callbacks.push(callback);??return;??}??this.queue[url]?=?{??callbacks:?[callback],??//?假設這里使用fetch進行請求??promise:?fetch(url).then(response?=>?{??const?data?=?response.json();??this.queue[url].callbacks.forEach(cb?=>?cb(data));??delete?this.queue[url];?//?請求完成后從隊列中移除??})??};??}??
}??//?使用??
const?queue?=?new?RequestQueue();??
queue.addRequest('https://api.example.com/data',?data?=>?{??console.log(data);??
});
2、?請求取消:在發送請求前,記錄當前正在進行的請求,并在發送新請求時先取消之前的請求。可以使用 Axios 等庫提供的取消請求功能來實現。
import?axios?from?'axios';??let?cancelTokenSource;??function?fetchData()?{??if?(cancelTokenSource)?{??cancelTokenSource.cancel('Operation?canceled?by?the?user.');?//?取消之前的請求??}??cancelTokenSource?=?axios.CancelToken.source();??axios.get('https://api.example.com/data',?{??cancelToken:?cancelTokenSource.token??}).then(response?=>?{??console.log(response.data);??}).catch(function?(thrown)?{??if?(axios.isCancel(thrown))?{??console.log('Request?canceled',?thrown.message);??}?else?{??//?處理錯誤??}??});??
}??//?調用fetchData時會取消之前的請求(如果存在)??
fetchData();
3、?防抖(Debounce):使用防抖函數控制請求的發送頻率,確保在一段時間內只發送一次請求。這樣可以避免頻繁的重復請求。
比較容易理解,代碼示例略了吧。
4、?節流(Throttle):與防抖類似,節流函數可以控制一段時間內請求的頻率,但不會像防抖那樣在每次觸發事件后立即執行,而是在固定間隔內執行一次。
比較容易理解,代碼示例略了吧。
5、?請求標識:為每個請求設置唯一標識,當新請求到來時,先檢查是否存在相同標識的請求,如果存在則不發送新請求。
比較容易理解,代碼示例略了吧。
6、?緩存請求結果:對于相同的請求,在第一次請求返回結果后將結果緩存起來,后續相同的請求可以直接使用緩存的結果,而不再發送重復請求。
比較容易理解,代碼示例略了吧。
7、?使用狀態管理庫:在 Vue 應用中,可以結合狀態管理庫(如 Vuex、Pinia)來管理請求狀態,確保只有一個請求在進行,避免重復請求。
//?Vuex?store配置??
const?store?=?new?Vuex.Store({??state:?{??isFetching:?false,??data:?null??},??mutations:?{??FETCH_START(state)?{??state.isFetching?=?true;??},??FETCH_END(state,?data)?{??state.isFetching?=?false;??state.data?=?data;??}??},??actions:?{??fetchData({?commit?})?{??if?(this.state.isFetching)?{??return;?//?如果已經在請求數據,則不再發送新請求??}??commit('FETCH_START');??return?fetch('https://api.example.com/data').then(response?=>?{??return?response.json();??}).then(data?=>?{??commit('FETCH_END',?data);??return?data;??});??}??}??
});??//?在Vue組件中使用??
this.$store.dispatch('fetchData').then(data?=>?{??console.log(data);??
});
收尾的時刻
程序員大澈,全網同名,感謝關注!
優質前后端領域公眾號博主,掘金年度人氣作者,抖音/小紅書/B站/頭條/知乎/CSDN等全網資深創作者,全網閱讀量100w+,專注于前后端技術知識分享。
加微信:CodeDache,交流學習,免費拉你進技術問答群。
關注微信公眾號:程序員大澈,文章首發,免費領取一份入行禮包。