自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:如何中斷已發(fā)出去的請求?

開發(fā) 前端
Fetch 是 Web 提供的一個用于獲取資源的接口,如果要終止 fetch 請求,則可以使用 Web 提供的 AbortController 接口。

 面試官:請求已經發(fā)出去了,如何取消掉這個已經發(fā)出去的請求?

面試者:(腦海里立馬產生一個疑惑:已經發(fā)出去的請求還能取消掉?) 這個......這個......還真不知道。

面試完,馬上找度娘.....

推薦閱讀:axios解析之cancelToken取消請求原理[2]

AbortController

AbortController[3] 接口表示一個控制器對象,可以根據需要終止一個或多個Web請求。

  •  AbortController():AbortController()構造函數創(chuàng)建一個新的 AbortController 對象實例
  •  signal:signal 屬性返回一個 AbortSignal 對象實例,它可以用來 with/about 一個Web(網絡)請求
  •  abort():終止一個尚未完成的Web(網絡)請求,它能夠終止 fetch 請求,任何響應Body的消費者和流

Fetch 中斷請求

Fetch 是 Web 提供的一個用于獲取資源的接口,如果要終止 fetch 請求,則可以使用 Web 提供的 AbortController 接口。

首先我們使用 AbortController() 構造函數創(chuàng)建一個控制器,然后使用 AbortController.signal 屬性獲取其關聯 AbortSignal 對象的引用。當一個 fetch request 初始化時,我們把 AbortSignal 作為一個選項傳遞到請求對象 (如下:{signal}) 。這將信號和控制器與獲取請求相關聯,然后允許我們通過調用 AbortController.abort() 中止請求。 

  1. const controller = new AbortController();  
  2. let signal = controller.signal;  
  3.  console.log('signal 的初始狀態(tài): ', signal);  
  4. const downloadBtn = document.querySelector('.download');  
  5. const abortBtn = document.querySelector('.abort');  
  6. downloadBtn.addEventListener('click', fetchVideo);  
  7. abortBtn.addEventListener('click', function() {  
  8.   controller.abort();  
  9.  console.log('signal 的中止狀態(tài): ', signal);  
  10. });  
  11. function fetchVideo() {  
  12.   //...  
  13.   fetch(url, {signal}).then(function(response) {  
  14.     //...  
  15.   }).catch(function(e) {  
  16.     reports.textContent = 'Download error: ' + e.message;  
  17.   })  
  18.  
  19. 復制代碼 

當我們中止請求后,網絡請求變成了如下所示的情況:

我們再來看看 AbortSignal 中止前和中止后的狀態(tài):

可以看到,AbortSignal 對象的 aborted 屬性由初始時的 false 變成了中止后的 true 。

線上運行示例[4] (代碼來源于MDN[5])

AbortControllter 有兼容性問題,如下:

axios 中斷請求

axions 中斷請求有兩種方式:

方式一

使用 CancelToken.souce 工廠方法創(chuàng)建一個 cancel token,代碼如下: 

  1. const CancelToken = axios.CancelToken;  
  2. const source = CancelToken.source();  
  3. axios.get('https://mdn.github.io/dom-examples/abort-api/sintel.mp4', {  
  4.   cancelToken: source.token  
  5. }).catch(function (thrown) {  
  6.   // 判斷請求是否已中止  
  7.   if (axios.isCancel(thrown)) {  
  8.     // 參數 thrown 是自定義的信息  
  9.     console.log('Request canceled', thrown.message);  
  10.   } else {  
  11.     // 處理錯誤  
  12.   }  
  13. });  
  14. // 取消請求(message 參數是可選的)  
  15. source.cancel('Operation canceled by the user.');  
  16. 復制代碼 

中止后的網絡請求變成如下所示:

我們再來看看初始時和中止后的 souce 狀態(tài):

可以看到,初始時和中止后的 source 狀態(tài)并沒還有發(fā)生改變。那么我們是如何判斷請求的中止狀態(tài)呢?axios 為我們提供了一個 isCancel() 方法,用于判斷請求的中止狀態(tài)。isCancel() 方法的參數,就是我們在中止請求時自定義的信息。

方式二

通過傳遞一個 executor 函數到 CancelToken 的構造函數來創(chuàng)建一個 cancel token: 

  1. const CancelToken = axios.CancelToken;  
  2. let cancel;  
  3. axios.get('/user/12345', { 
  4.   cancelToken: new CancelToken(function executor(c) {  
  5.     // executor 函數接收一個 cancel 函數作為參數  
  6.     ccancel = c;  
  7.   })  
  8. });  
  9. // 取消請求  
  10. cancel('Operation canceled by the user.');  
  11. 復制代碼 

瀏覽器運行結果與方式一一致,此處不再贅述。

線上運行示例[6] (代碼來源于MDN[7])

umi-request 中斷請求

umi-request 基于 fetch 封裝, 兼具 fetch 與 axios 的特點, 中止請求與 fetch 和 axios 一致不再過多贅述,詳情可見官方文檔 中止請求[8]

需要注意的是 AbortController 在低版本瀏覽器polyfill有問題,umi-request 在某些版本中并未提供 AbortController 的方式中止請求。

umi 項目中使用 CancelToken 中止請求

umi 項目中默認的請求庫是umi-request,因此我們可以使用umi-request提供的方法來中止請求。另外,在umi項目中可以搭配使用了dva,因此下面簡單介紹下在dva中使用CancelToken中止請求的流程。

1、在 services 目錄下的文件中編寫請求函數和取消請求的函數 

  1. import request from '@/utils/request';  
  2. const CancelToken = request.CancelToken;  
  3. let cancel: any;  
  4. // 合同文件上傳 OSS  
  5. export async function uploadContractFileToOSS(postBody: Blob): Promise<any> {  
  6.   return request(`/fms/ossUpload/financial_sys/contractFile`, {  
  7.     method: "POST",  
  8.     data: postBody,  
  9.     requestType: 'form',  
  10.     // 傳遞一個 executor 函數到 CancelToken 的構造函數來創(chuàng)建一個 cancel token  
  11.     cancelToken: new CancelToken((c) => {  
  12.       ccancel = c  
  13.     })  
  14.   })  
  15.  
  16. // 取消合同文件上傳  
  17. export async function cancelUploadFile() {  
  18.   return cancel && cancel()  
  19.  
  20. 復制代碼 

2、在 models 中編寫 Effect: 

  1. *uploadContractFileToOSS({ payload }: AnyAction, { call, put }: EffectsCommandMap): any {  
  2.   const response = yield call(uploadContractFileToOSS, payload);  
  3.   yield put({  
  4.     type: 'save',  
  5.     payload: {  
  6.       uploadOSSResult: response?.data,  
  7.     }  
  8.   })  
  9.   return response?.data  
  10. },  
  11. *cancelUploadFile(_: AnyAction, { call }: EffectsCommandMap): any {  
  12.   const response = yield call(cancelUploadFile)  
  13.   return response  
  14. },  
  15. 復制代碼 

3、在頁面中通過dispatch函數觸發(fā)相應的action: 

  1. // 發(fā)起請求  
  2. dispatch({  
  3.   type: 'contract/fetchContractFiles',  
  4.   payload: {  
  5.     contractId: `${id}`,  
  6.   }  
  7. })  
  8. // 取消請求  
  9. dispatch({  
  10.   type: "contract/cancelUploadFile"  
  11. })    
  12. 復制代碼 

4、在 utils/request.js 中統(tǒng)一處理中止請求的攔截: 

  1. const errorHandler = (error: { response: Response }): Response => {  
  2.   const { response } = error;  
  3.   notification.destroy()  
  4.   if (response && response.status) {  
  5.     const errorText = codeMessage[response.status] || response.statusText;  
  6.     const { status, url } = response;  
  7.     notification.error({  
  8.       message: `請求錯誤 ${status}: ${url}`,  
  9.       description: errorText,  
  10.     });  
  11.   } else if (error?.['type'] === 'TypeError') {  
  12.     notification.error({  
  13.       description: '您的網絡發(fā)生異常,無法連接服務器',  
  14.       message: '網絡異常',  
  15.     });  
  16.   } else if (error?.['request']?.['options']?.['cancelToken']) {  
  17.     notification.warn({  
  18.       description: '當前請求已被取消',  
  19.       message: '取消請求',  
  20.     });  
  21.   } else if (!response) {  
  22.     notification.error({  
  23.       description: '您的網絡發(fā)生異常,無法連接服務器',  
  24.       message: '網絡異常',  
  25.     });  
  26.   } else {  
  27.     notification.error({  
  28.       description: '請聯系網站開發(fā)人員處理', 
  29.       message: '未知錯誤',  
  30.     });  
  31.   }  
  32.   return response;  
  33. };  
  34. 復制代碼  

 

責任編輯:龐桂玉 來源: Web開發(fā)
相關推薦

2015-08-13 10:29:12

面試面試官

2022-04-01 12:38:32

cookie代碼面試

2021-01-18 05:13:04

TomcatHttp

2010-08-12 16:28:35

面試官

2023-02-16 08:10:40

死鎖線程

2020-06-12 15:50:56

options前端服務器

2024-03-18 14:06:00

停機Spring服務器

2024-02-20 14:10:55

系統(tǒng)緩存冗余

2021-07-06 07:08:18

管控數據數倉

2024-09-11 22:51:19

線程通訊Object

2024-04-03 00:00:00

Redis集群代碼

2025-03-17 00:00:00

2023-11-20 10:09:59

2021-05-27 05:37:10

HTTP請求頭瀏覽器

2023-10-08 15:23:12

2015-08-24 09:00:36

面試面試官

2024-02-04 10:08:34

2024-12-25 15:44:15

2024-05-11 15:11:44

系統(tǒng)軟件部署

2024-01-19 14:03:59

Redis緩存系統(tǒng)Spring
點贊
收藏

51CTO技術棧公眾號