JavaScript如何實(shí)現(xiàn)防止重復(fù)的網(wǎng)絡(luò)請求的示例
前言
在開發(fā)中,經(jīng)常會遇到接口重復(fù)請求導(dǎo)致的各種問題。
對于重復(fù)的網(wǎng)絡(luò)請求,會導(dǎo)致頁面更新多次,發(fā)生頁面抖動的現(xiàn)象,影響用戶體驗(yàn)。
例如當(dāng)前頁面請求還未響應(yīng)完成,就切換到其他路由,那么這些請求直到響應(yīng)返回才會中止。
無論從用戶體驗(yàn)或者從業(yè)務(wù)嚴(yán)謹(jǐn)方面來說,取消無用的請求確實(shí)是需要避免的。
實(shí)現(xiàn)思路

** 1.在發(fā)送請求前先攔截當(dāng)前請求地址 (url + 方法 + 參數(shù));
** 2.開啟一個(gè)請求隊(duì)列用于保存 當(dāng)前地址;
** 3.每次請求查看請求隊(duì)列里面有沒有當(dāng)前url地址;
** 4.如果請求隊(duì)列里有當(dāng)前url地址就取消當(dāng)前請求,
** 5.如果沒有就發(fā)送請求,當(dāng)請求數(shù)據(jù)返回后,請求隊(duì)列里清除當(dāng)前url地址。
1.平時(shí)我們寫接口是這樣的:
請求接口文件
import { http } from '@/plugin/axios'; // 導(dǎo)入請求接口 http
// 初始化
export function getInit(params) {
return http({
method: 'get',
url: '/xxx/xxx/xx',
params,
});
}
主要就是這里執(zhí)行 http方法的時(shí)候做操作;
執(zhí)行http函數(shù)的時(shí)候能獲取到請求所有配置 config ,返回promise對象。
2.這里演示使用axios,思路是執(zhí)行請求函數(shù)的時(shí)候外面包一層
axios.js配置文件
import axios from 'axios';
import { httpRequest, completeRequest } from './options'; // 這里就是我們要實(shí)現(xiàn)的邏輯文件
// 里面做一些請求攔截,響應(yīng)攔截操作 具體查看axios文檔
const service = axios.create({
baseURL: 'xxx/xxx',
});
// 請求攔截器
service.interceptors.request.use(config => {}, error => {})
// 響應(yīng)攔截器
service.interceptors.response.use(response => {
completeRequest(response); // 2.響應(yīng)請求回來執(zhí)行
}, error => {
})
export function http(config) { // => 這里config就是傳遞的請求配置參數(shù)
return httpRequest(config, service); // + 1.在這里做一些邏輯操作
}
3.防止重復(fù)網(wǎng)絡(luò)配置文件
options.js
(1)發(fā)送請求前,查看請求隊(duì)列里是否有當(dāng)前請求(url地址來判斷)
- 請求隊(duì)列有當(dāng)前url地址, 取消請求 返回promise.reject失敗
- 沒有當(dāng)前請求,正常發(fā)送請求;
/**
* 職責(zé): 防止重復(fù)的網(wǎng)絡(luò)請求
*
*/
let list = new Set(); // 1.請求隊(duì)列
// 合并 方法 參數(shù) url地址
function getUrl(config = {}) {
// get請求 params參數(shù) post請求 data參數(shù), baseURL
const { url, method, params, data, baseURL = '' } = config;
const urlVal = url.replace(baseURL, '');
return `${urlVal}?${method === 'get' ? getformatObjVal(params) : getformatObjVal(data)}`;
}
// 處理 url地址
const getformatObjVal = (obj) => {
obj = typeof obj === 'string' ? JSON.parse(`${obj}`) : obj;
var str = [];
for (let p in obj) {
if (obj.hasOwnProperty(p) && p !== '_t') {
var item = obj[p] === null ? '' : obj[p]; // 處理null
str.push(encodeURIComponent(p) + '=' + encodeURIComponent(item));
}
}
return str.join('&');
}
// 2.請求方法
export function httpRequest(config = {}, axios) {
const url = getUrl(config); //3. 這里我們獲取到了URL地址
if (list.has(url)) { // 4.查看請求隊(duì)列是否有當(dāng)前url地址
return Promise.reject('In the request'); // 5.在請求隊(duì)列里面 取消當(dāng)前請求, 返回Promise失敗結(jié)果
}
// 6. 請求隊(duì)列沒有當(dāng)前url地址 發(fā)送請求并把url地址存入請求隊(duì)列里
list.add(url);
return Promise.resolve(axios);
}
(2)請求響應(yīng)回來后,在請求隊(duì)列里刪除當(dāng)前url地址; (下一次請求就可以正常發(fā)送)
options.js
// 請求響應(yīng)回來執(zhí)行這個(gè)函數(shù)
export function completeRequest(response = {}) {
const { config } = response; // 1.response里面config能拿到配置參數(shù)
const url = getUrl(config); // 2.獲取url地址
if (list.has(url)) {
list.delete(url); // 3.刪除請求隊(duì)列中的當(dāng)前請求url地址
}
}
axios.js
import axios from 'axios';
import { httpRequest, completeRequest } from './options'; // 防止重復(fù)請求
const service = axios.create({
baseURL: 'xxx/xxx',
});
// 請求攔截器
service.interceptors.request.use(config => {}, error => {})
// 響應(yīng)攔截器
service.interceptors.response.use(response => {
completeRequest(response); // 2.響應(yīng)請求回來執(zhí)行 +
}, error => {
})
// 導(dǎo)出請求
export function http(config) {
return httpRequest(config, service); // 1.發(fā)送請求前執(zhí)行
}
到這里已經(jīng)實(shí)現(xiàn)了防止重復(fù)的網(wǎng)絡(luò)請求,但還有一個(gè)問題,響應(yīng)請求發(fā)生異常了要清除請求隊(duì)列中當(dāng)前url地址。不清理,下一次發(fā)送請求直接被取消掉 (這里我就隨便寫了一個(gè)方法,把請求隊(duì)列全部清空,大家可以按自己場景來寫)。
/**
* 清空所有請求隊(duì)列
*/
export function clearRequestList() {
list = new Set(); // 這里我就直接清空了
}
完整http.js文件
import axios from 'axios';
import { httpRequest, completeRequest, clearRequestList } from './options'; // 防止重復(fù)請求 +
const service = axios.create({
baseURL: 'xxx/xxx',
});
// 請求攔截器
service.interceptors.request.use(config => {}, error => {})
// 響應(yīng)攔截器
service.interceptors.response.use(response => {
completeRequest(response); // 2.響應(yīng)請求回來執(zhí)行
}, error => {
clearRequestList(); // +
})
// 導(dǎo)出請求
export function http(config) {
return httpRequest(config, service); // 1.發(fā)送請求前執(zhí)行
}
完整options.js
/**
* 職責(zé): 防止重復(fù)的網(wǎng)絡(luò)請求
*
*/
let list = new Set(); // 1.請求隊(duì)列
// 合并 方法 參數(shù) url地址
function getUrl(config = {}) {
// get請求 params參數(shù) post請求 data參數(shù), baseURL
const { url, method, params, baseURL = '' } = config;
const urlVal = url.replace(baseURL, '');
return `${urlVal}?${method === 'get' ? getformatObjVal(params) : 'post'}`;
}
// 處理 url地址
const getformatObjVal = (obj) => {
obj = typeof obj === 'string' ? JSON.parse(`${obj}`) : obj;
var str = [];
for (let p in obj) {
if (obj.hasOwnProperty(p) && p !== '_t') {
var item = obj[p] === null ? '' : obj[p]; // 處理null
str.push(encodeURIComponent(p) + '=' + encodeURIComponent(item));
}
}
return str.join('&');
}
// 2.請求方法
export function httpRequest(config = {}, axios) {
const url = getUrl(config); //3. 這里我們獲取到了URL地址
if (list.has(url)) { // 4.查看請求隊(duì)列是否有當(dāng)前url地址
return Promise.reject('In the request'); // 5.在請求隊(duì)列里面 取消當(dāng)前請求, 返回Promise失敗結(jié)果
}
// 6. 請求隊(duì)列沒有當(dāng)前url地址 發(fā)送請求并把url地址存入請求隊(duì)列里
list.add(url);
return Promise.resolve(axios);
}
/**
* 請求響應(yīng)回來執(zhí)行這個(gè)函數(shù)
*/
export function completeRequest(response = {}) {
const { config } = response; // 1.response里面config能拿到配置參數(shù)
const url = getUrl(config); // 2.獲取url地址
list.has(url) && list.delete(url); // 3.刪除請求隊(duì)列中的當(dāng)前請求url地址
}
/**
* 清空所有請求隊(duì)列
*/
export function clearRequestList(error) {
// error 可以獲取到配置, 做一些操作。
list = new Set(); // 這里我就直接清空了
}
以上就是我實(shí)現(xiàn)防止網(wǎng)絡(luò)請求的方式,之前我有使用過axios中CancelToken來進(jìn)行取消請求;當(dāng)會有一些問題。
- 需要配置請求文件,不友好,團(tuán)隊(duì)開發(fā)配置也比較麻煩。
- 需要給每個(gè)請求都配置CancelToken。 有兩個(gè)方法使用它 具體可以參考官網(wǎng)文檔
到此這篇關(guān)于JavaScript如何實(shí)現(xiàn)防止重復(fù)的網(wǎng)絡(luò)請求的示例的文章就介紹到這了,更多相關(guān)JavaScript 防止重復(fù)的網(wǎng)絡(luò)請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript根據(jù)數(shù)據(jù)生成百分比圖和柱狀圖的實(shí)例代碼
這篇文章介紹了JavaScript根據(jù)數(shù)據(jù)生成百分比圖和柱狀圖的實(shí)例代碼,有需要的朋友可以參考一下2013-07-07
基于JS+Canvas的lucky-canvas?抽獎(jiǎng)功能
一個(gè)基于?Js?+?Canvas?的大轉(zhuǎn)盤和九宮格和老虎機(jī)抽獎(jiǎng),使用lucky-canvas?功能可以自由配置,多端適配的特點(diǎn),本文通過實(shí)例代碼給大家詳細(xì)介紹抽獎(jiǎng)方法,感興趣的朋友一起看看吧2022-06-06
JavaScript 原型繼承之構(gòu)造函數(shù)繼承
JavaScript 是基于原型的面向?qū)ο笳Z言。也就是說,每個(gè)實(shí)例對象都具有一個(gè)原型。對象從該原型中繼承屬性和方法。這一篇將具體說說構(gòu)造函數(shù)的繼承。2011-08-08
AngularJS實(shí)現(xiàn)textarea記錄只能輸入規(guī)定數(shù)量的字符并顯示
AngularJS 是一個(gè) MV* 框架,最適于開發(fā)客戶端的單頁面應(yīng)用。它不是個(gè)功能庫,而是用來開發(fā)動態(tài)網(wǎng)頁的框架。接下來通過本文給大家介紹AngularJS實(shí)現(xiàn)textarea記錄只能輸入規(guī)定數(shù)量的字符并顯示的相關(guān)內(nèi)容,需要的朋友參考下吧2016-04-04
JavaScript裝箱及拆箱boxing及unBoxing用法解析
這篇文章主要介紹了JavaScript裝箱及拆箱boxing及unBoxing用法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
如何利用js實(shí)時(shí)監(jiān)聽input輸入框值的變化
在做web開發(fā)時(shí)候很多時(shí)候都需要即時(shí)監(jiān)聽輸入框值的變化,以便作出即時(shí)動作去引導(dǎo)瀏覽者增強(qiáng)網(wǎng)站的用戶體驗(yàn)感,這篇文章主要給大家介紹了關(guān)于如何利用js實(shí)時(shí)監(jiān)聽input輸入框值的變化,需要的朋友可以參考下2024-02-02

