1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 7606字,需瀏覽 16分鐘

         ·

        2022-01-01 18:35


        點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注

        這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包
        真愛,請(qǐng)?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看
        作者:紫圣
        https://juejin.cn/post/7033906910583586829

        面試官:請(qǐng)求已經(jīng)發(fā)出去了,如何取消掉這個(gè)已經(jīng)發(fā)出去的請(qǐng)求?
        面試者:(腦海里立馬產(chǎn)生一個(gè)疑惑:已經(jīng)發(fā)出去的請(qǐng)求還能取消掉?) 這個(gè)......這個(gè)......還真不知道。
        面試完,馬上找度娘.....
        推薦閱讀:axios解析之cancelToken取消請(qǐng)求原理[2]

        AbortController

        AbortController[3] 接口表示一個(gè)控制器對(duì)象,可以根據(jù)需要終止一個(gè)或多個(gè)Web請(qǐng)求。
        • AbortController():AbortController()構(gòu)造函數(shù)創(chuàng)建一個(gè)新的 AbortController 對(duì)象實(shí)例

        • signal:signal 屬性返回一個(gè) AbortSignal 對(duì)象實(shí)例,它可以用來 with/about 一個(gè)Web(網(wǎng)絡(luò))請(qǐng)求

        • abort():終止一個(gè)尚未完成的Web(網(wǎng)絡(luò))請(qǐng)求,它能夠終止 fetch 請(qǐng)求,任何響應(yīng)Body的消費(fèi)者和流

        Fetch 中斷請(qǐng)求

        Fetch 是 Web 提供的一個(gè)用于獲取資源的接口,如果要終止 fetch 請(qǐng)求,則可以使用 Web 提供的 AbortController 接口。
        首先我們使用 AbortController() 構(gòu)造函數(shù)創(chuàng)建一個(gè)控制器,然后使用 AbortController.signal 屬性獲取其關(guān)聯(lián) AbortSignal 對(duì)象的引用。當(dāng)一個(gè) fetch request 初始化時(shí),我們把 AbortSignal 作為一個(gè)選項(xiàng)傳遞到請(qǐng)求對(duì)象 (如下:{signal}) 。這將信號(hào)和控制器與獲取請(qǐng)求相關(guān)聯(lián),然后允許我們通過調(diào)用 AbortController.abort() 中止請(qǐng)求。
        const controller = new AbortController();
        let signal = controller.signal;
         console.log('signal 的初始狀態(tài): ', signal);

        const downloadBtn = document.querySelector('.download');
        const abortBtn = document.querySelector('.abort');

        downloadBtn.addEventListener('click', fetchVideo);

        abortBtn.addEventListener('click'function() {
          controller.abort();
         console.log('signal 的中止?fàn)顟B(tài): ', signal);
        });

        function fetchVideo() {
          //...
          fetch(url, {signal}).then(function(response) {
            //...
          }).catch(function(e) {
            reports.textContent = 'Download error: ' + e.message;
          })
        }
        復(fù)制代碼
        當(dāng)我們中止請(qǐng)求后,網(wǎng)絡(luò)請(qǐng)求變成了如下所示的情況:
        我們?cè)賮砜纯?AbortSignal 中止前和中止后的狀態(tài):
        可以看到,AbortSignal 對(duì)象的 aborted 屬性由初始時(shí)的 false 變成了中止后的 true 。
        線上運(yùn)行示例[4] (代碼來源于MDN[5])
        AbortControllter 有兼容性問題,如下:

        axios 中斷請(qǐng)求

        axions 中斷請(qǐng)求有兩種方式:
        方式一
        使用 CancelToken.souce 工廠方法創(chuàng)建一個(gè) cancel token,代碼如下:
        const CancelToken = axios.CancelToken;
        const source = CancelToken.source();

        axios.get('https://mdn.github.io/dom-examples/abort-api/sintel.mp4', {
          cancelToken: source.token
        }).catch(function (thrown) {
          // 判斷請(qǐng)求是否已中止
          if (axios.isCancel(thrown)) {
            // 參數(shù) thrown 是自定義的信息
            console.log('Request canceled', thrown.message);
          } else {
            // 處理錯(cuò)誤
          }
        });

        // 取消請(qǐng)求(message 參數(shù)是可選的)
        source.cancel('Operation canceled by the user.');
        復(fù)制代碼
        中止后的網(wǎng)絡(luò)請(qǐng)求變成如下所示:
        我們?cè)賮砜纯闯跏紩r(shí)和中止后的 souce 狀態(tài):
        可以看到,初始時(shí)和中止后的 source 狀態(tài)并沒還有發(fā)生改變。那么我們是如何判斷請(qǐng)求的中止?fàn)顟B(tài)呢?axios 為我們提供了一個(gè) isCancel() 方法,用于判斷請(qǐng)求的中止?fàn)顟B(tài)。isCancel() 方法的參數(shù),就是我們?cè)谥兄拐?qǐng)求時(shí)自定義的信息。
        方式二
        通過傳遞一個(gè) executor 函數(shù)到 CancelToken 的構(gòu)造函數(shù)來創(chuàng)建一個(gè) cancel token:
        const CancelToken = axios.CancelToken;
        let cancel;

        axios.get('/user/12345', {
          cancelToken: new CancelToken(function executor(c) {
            // executor 函數(shù)接收一個(gè) cancel 函數(shù)作為參數(shù)
            cancel = c;
          })
        });

        // 取消請(qǐng)求
        cancel('Operation canceled by the user.');
        復(fù)制代碼
        瀏覽器運(yùn)行結(jié)果與方式一一致,此處不再贅述。
        線上運(yùn)行示例[6] (代碼來源于MDN[7])

        umi-request 中斷請(qǐng)求

        umi-request 基于 fetch 封裝, 兼具 fetch 與 axios 的特點(diǎn), 中止請(qǐng)求與 fetch 和 axios 一致不再過多贅述,詳情可見官方文檔 中止請(qǐng)求[8]
        需要注意的是 AbortController 在低版本瀏覽器polyfill有問題,umi-request 在某些版本中并未提供 AbortController 的方式中止請(qǐng)求。

        umi 項(xiàng)目中使用 CancelToken 中止請(qǐng)求

        umi 項(xiàng)目中默認(rèn)的請(qǐng)求庫是umi-request,因此我們可以使用umi-request提供的方法來中止請(qǐng)求。另外,在umi項(xiàng)目中可以搭配使用了dva,因此下面簡(jiǎn)單介紹下在dva中使用CancelToken中止請(qǐng)求的流程。
        1、在 services 目錄下的文件中編寫請(qǐng)求函數(shù)和取消請(qǐng)求的函數(shù)
        import request from '@/utils/request';
        const CancelToken = request.CancelToken;
        let cancel: any;

        // 合同文件上傳 OSS
        export async function uploadContractFileToOSS(postBody: Blob): Promise<any> {
          return request(`/fms/ossUpload/financial_sys/contractFile`, {
            method: "POST",
            data: postBody,
            requestType: 'form',
            // 傳遞一個(gè) executor 函數(shù)到 CancelToken 的構(gòu)造函數(shù)來創(chuàng)建一個(gè) cancel token
            cancelToken: new CancelToken((c) => {
              cancel = c
            })
          })
        }

        // 取消合同文件上傳
        export async function cancelUploadFile() {
          return cancel && cancel()
        }
        復(fù)制代碼
        2、在 models 中編寫 Effect:
        *uploadContractFileToOSS({ payload }: AnyAction, { call, put }: EffectsCommandMap): any {
          const response = yield call(uploadContractFileToOSS, payload);
          yield put({
            type'save',
            payload: {
              uploadOSSResult: response?.data,
            }
          })
          return response?.data
        },

        *cancelUploadFile(_: AnyAction, { call }: EffectsCommandMap): any {
          const response = yield call(cancelUploadFile)
          return response

        },
        復(fù)制代碼
        3、在頁面中通過dispatch函數(shù)觸發(fā)相應(yīng)的action:
        // 發(fā)起請(qǐng)求
        dispatch({
          type'contract/fetchContractFiles',
          payload: {
            contractId: `${id}`,
          }
        })

        // 取消請(qǐng)求
        dispatch({
          type"contract/cancelUploadFile"
        })
           
        復(fù)制代碼
        4、在 utils/request.js 中統(tǒng)一處理中止請(qǐng)求的攔截:
        const errorHandler = (error: { response: Response }): Response => {
          const { response } = error;
          notification.destroy()

          if (response && response.status) {
            const errorText = codeMessage[response.status] || response.statusText;
            const { status, url } = response;

            notification.error({
              message: `請(qǐng)求錯(cuò)誤 ${status}${url}`,
              description: errorText,
            });
          } else if (error?.['type'] === 'TypeError') {
            notification.error({
              description: '您的網(wǎng)絡(luò)發(fā)生異常,無法連接服務(wù)器',
              message: '網(wǎng)絡(luò)異常',
            });
          } else if (error?.['request']?.['options']?.['cancelToken']) {
            notification.warn({
              description: '當(dāng)前請(qǐng)求已被取消',
              message: '取消請(qǐng)求',
            });
          } else if (!response) {
            notification.error({
              description: '您的網(wǎng)絡(luò)發(fā)生異常,無法連接服務(wù)器',
              message: '網(wǎng)絡(luò)異常',
            });
          } else {
            notification.error({
              description: '請(qǐng)聯(lián)系網(wǎng)站開發(fā)人員處理',
              message: '未知錯(cuò)誤',
            });
          }
          return response;
        };
        復(fù)制代碼

        -End-

        最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

        點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

        瀏覽 45
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            9丨PORNY九色9l祝频 | 秘书边打电话边被躁bd中文字幕 | 青娱乐国产在线视频 | 第四色在线视频 | 美女奶子无遮挡 | 日本一卡二卡三卡 | 操老逼| 久久精品国产精品青草 | 青草色天堂 | 国产伦精品一区二区三区视频网站 |