前言
在開發中,經常會遇到接口重復請求導致的各種問題。
對于重復的網絡請求,會導致頁面更新多次,發生頁面抖動的現象,影響用戶體驗。
例如當前頁面請求還未響應完成,就切換到其他路由,那么這些請求直到響應返回才會中止。
無論從用戶體驗或者從業務嚴謹方面來說,取消無用的請求確實是需要避免的。
實現思路
** 1.在發送請求前先攔截當前請求地址 (url + 方法 + 參數);
** 2.開啟一個請求隊列用于保存 當前地址;
** 3.每次請求查看請求隊列里面有沒有當前url地址;
** 4.如果請求隊列里有當前url地址就取消當前請求,
** 5.如果沒有就發送請求,當請求數據返回后,請求隊列里清除當前url地址。
1.平時我們寫接口是這樣的:
請求接口文件
1
2
3
4
5
6
7
8
9
10
|
import { http } from '@/plugin/axios' ; // 導入請求接口 http // 初始化 export function getInit(params) { return http({ method: 'get' , url: '/xxx/xxx/xx' , params, }); } |
主要就是這里執行 http方法的時候做操作;
執行http函數的時候能獲取到請求所有配置 config ,返回promise對象。
2.這里演示使用axios,思路是執行請求函數的時候外面包一層
axios.js配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import axios from 'axios' ; import { httpRequest, completeRequest } from './options' ; // 這里就是我們要實現的邏輯文件 // 里面做一些請求攔截,響應攔截操作 具體查看axios文檔 const service = axios.create({ baseURL: 'xxx/xxx' , }); // 請求攔截器 service.interceptors.request.use(config => {}, error => {}) // 響應攔截器 service.interceptors.response.use(response => { completeRequest(response); // 2.響應請求回來執行 }, error => { }) export function http(config) { // => 這里config就是傳遞的請求配置參數 return httpRequest(config, service); // + 1.在這里做一些邏輯操作 } |
3.防止重復網絡配置文件
options.js
(1)發送請求前,查看請求隊列里是否有當前請求(url地址來判斷)
- 請求隊列有當前url地址, 取消請求 返回promise.reject失敗
- 沒有當前請求,正常發送請求;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/** * 職責: 防止重復的網絡請求 * */ let list = new Set(); // 1.請求隊列 // 合并 方法 參數 url地址 function getUrl(config = {}) { // get請求 params參數 post請求 data參數, 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.查看請求隊列是否有當前url地址 return Promise.reject( 'In the request' ); // 5.在請求隊列里面 取消當前請求, 返回Promise失敗結果 } // 6. 請求隊列沒有當前url地址 發送請求并把url地址存入請求隊列里 list.add(url); return Promise.resolve(axios); } |
(2)請求響應回來后,在請求隊列里刪除當前url地址; (下一次請求就可以正常發送)
? options.js
1
2
3
4
5
6
7
8
|
// 請求響應回來執行這個函數 export function completeRequest(response = {}) { const { config } = response; // 1.response里面config能拿到配置參數 const url = getUrl(config); // 2.獲取url地址 if (list.has(url)) { list. delete (url); // 3.刪除請求隊列中的當前請求url地址 } } |
axios.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import axios from 'axios' ; import { httpRequest, completeRequest } from './options' ; // 防止重復請求 const service = axios.create({ baseURL: 'xxx/xxx' , }); // 請求攔截器 service.interceptors.request.use(config => {}, error => {}) // 響應攔截器 service.interceptors.response.use(response => { completeRequest(response); // 2.響應請求回來執行 + }, error => { }) // 導出請求 export function http(config) { return httpRequest(config, service); // 1.發送請求前執行 } |
到這里已經實現了防止重復的網絡請求,但還有一個問題,響應請求發生異常了要清除請求隊列中當前url地址。不清理,下一次發送請求直接被取消掉 (這里我就隨便寫了一個方法,把請求隊列全部清空,大家可以按自己場景來寫)。
1
2
3
4
5
6
|
/** * 清空所有請求隊列 */ export function clearRequestList() { list = new Set(); // 這里我就直接清空了 } |
完整http.js文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import axios from 'axios' ; import { httpRequest, completeRequest, clearRequestList } from './options' ; // 防止重復請求 + const service = axios.create({ baseURL: 'xxx/xxx' , }); // 請求攔截器 service.interceptors.request.use(config => {}, error => {}) // 響應攔截器 service.interceptors.response.use(response => { completeRequest(response); // 2.響應請求回來執行 }, error => { clearRequestList(); // + }) // 導出請求 export function http(config) { return httpRequest(config, service); // 1.發送請求前執行 } |
完整options.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
/** * 職責: 防止重復的網絡請求 * */ let list = new Set(); // 1.請求隊列 // 合并 方法 參數 url地址 function getUrl(config = {}) { // get請求 params參數 post請求 data參數, 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.查看請求隊列是否有當前url地址 return Promise.reject( 'In the request' ); // 5.在請求隊列里面 取消當前請求, 返回Promise失敗結果 } // 6. 請求隊列沒有當前url地址 發送請求并把url地址存入請求隊列里 list.add(url); return Promise.resolve(axios); } /** * 請求響應回來執行這個函數 */ export function completeRequest(response = {}) { const { config } = response; // 1.response里面config能拿到配置參數 const url = getUrl(config); // 2.獲取url地址 list.has(url) && list. delete (url); // 3.刪除請求隊列中的當前請求url地址 } /** * 清空所有請求隊列 */ export function clearRequestList(error) { // error 可以獲取到配置, 做一些操作。 list = new Set(); // 這里我就直接清空了 } |
以上就是我實現防止網絡請求的方式,之前我有使用過axios中CancelToken來進行取消請求;當會有一些問題。
- 需要配置請求文件,不友好,團隊開發配置也比較麻煩。
- 需要給每個請求都配置CancelToken。 有兩個方法使用它 具體可以參考官網文檔
到此這篇關于JavaScript如何實現防止重復的網絡請求的示例的文章就介紹到這了,更多相關JavaScript 防止重復的網絡請求內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://juejin.cn/post/6921985318698614792