JavaScript Fetch API請(qǐng)求和響應(yīng)攔截詳解
引言
本文翻譯自 Intercepting JavaScript Fetch API requests and responses
攔截器是可用于預(yù)處理或后處理 HTTP 請(qǐng)求的代碼塊,有助于全局錯(cuò)誤處理、身份驗(yàn)證、日志記錄等。在本文中,你將學(xué)習(xí)如何攔截 JavaScript Fetch API 請(qǐng)求。
攔截 HTTP 請(qǐng)求一般有兩種事件:請(qǐng)求和響應(yīng)事件。請(qǐng)求攔截器應(yīng)該在發(fā)送實(shí)際 HTTP 請(qǐng)求之前執(zhí)行,而響應(yīng)攔截器應(yīng)該在到達(dá)發(fā)出請(qǐng)求的應(yīng)用程序代碼之前執(zhí)行。
在深入研究代碼之前,我們需要了解一些重要的事情。首先,Fetch API 本身不支持?jǐn)r截器。其次,在 Node.js 中使用 Fetch API 需要額外的包。
JavaScript Fetch API
首先,讓我們介紹一些 Fetch API 的基礎(chǔ),例如語(yǔ)法:
const fetchResponsePromise = fetch(resource [, init])
resource
定義要獲取的資源,該資源可以是 Request 對(duì)象,也可以是 URL。init
是一個(gè)可選對(duì)象,它將包含你想應(yīng)用于此特定請(qǐng)求的任何自定義配置。
Fetch API 是基于 Promise 的。因此,當(dāng)你調(diào)用 Fetch 方法時(shí),你將得到一個(gè) Promise 響應(yīng)。在這里,它被稱為 fetchResponsePromise
,如上面的示例所示。
默認(rèn)情況下,F(xiàn)etch 使用 GET
方法調(diào)用 API,如下所示:
fetch('https://jsonplaceholder.typicode.com/todos/1') .then((response) => response.json()) .then((json) => console.log(json));
下面是一個(gè)使用 Fetch 發(fā)送 POST
請(qǐng)求的示例:
fetch('https://jsonplaceholder.typicode.com/todos', { method: 'POST', body: JSON.stringify({ completed: false, id: 1, title: 'New Todo', userId: 1, }), headers: new Headers({ 'Content-Type': 'application/json; charset=UTF-8', }), }) .then((response) => response.json()) .then((json) => console.log(json));
POST
請(qǐng)求必須有 body
。 查看 Fetch 文檔 了解更多詳細(xì)信息。
實(shí)現(xiàn)攔截
有兩種方法可以在 Fetch API 請(qǐng)求時(shí)添加攔截器:使用猴子補(bǔ)丁或者使用庫(kù) fetch-intercept。
對(duì) Fetch 使用猴子補(bǔ)?。╩onkey patching)
為任何 JavaScript 函數(shù)或方法創(chuàng)建攔截器的一種方法是對(duì)其進(jìn)行猴子修補(bǔ)。猴子補(bǔ)丁是一種用自己的函數(shù)版本覆蓋原始函數(shù)的方法。
讓我們一步一步地看看如何使用猴子補(bǔ)丁為 Fetch API 創(chuàng)建攔截器:
const { fetch: originalFetch } = window; window.fetch = async (...args) => { let [resource, config ] = args; // request interceptor here const response = await originalFetch(resource, config); // response interceptor here return response; };
上面的代碼使用自定義實(shí)現(xiàn)重寫原始 Fetch 方法,并在其中調(diào)用原始 Fetch 方法。你可以使用這個(gè)樣例代碼來創(chuàng)建請(qǐng)求和響應(yīng)攔截器。
請(qǐng)求攔截器
在下面的示例中,我們將創(chuàng)建一個(gè)簡(jiǎn)單的請(qǐng)求攔截器,用于更改一個(gè)請(qǐng)求示例的 URL:
const { fetch: originalFetch } = window; window.fetch = async (...args) => { let [resource, config ] = args; // request interceptor starts resource = 'https://jsonplaceholder.typicode.com/todos/2'; // request interceptor ends const response = await originalFetch(resource, config); // response interceptor here return response; }; fetch('https://jsonplaceholder.typicode.com/todos/1') .then((response) => response.json()) .then((json) => console.log(json)); // log // { // "userId": 1, // "id": 2, // "title": "quis ut nam facilis et officia qui", // "completed": false // }
這個(gè) API 請(qǐng)求將從 https://jsonplaceholder.typicode.com/todos/2
獲取數(shù)據(jù),而不是 https://jsonplaceholder.typicode.com/todos/1
,并展示 ID 為 2
的 todo
數(shù)據(jù)。
注意: 請(qǐng)求攔截器最常見的用例之一是更改身份驗(yàn)證的 headers。
響應(yīng)攔截器
響應(yīng)攔截器將在 API 響應(yīng)傳遞給實(shí)際調(diào)用者之前攔截它。讓我們看看下面的代碼:
const { fetch: originalFetch } = window; window.fetch = async (...args) => { let [resource, config] = args; let response = await originalFetch(resource, config); // response interceptor const json = () => response .clone() .json() .then((data) => ({ ...data, title: `Intercepted: ${data.title}` })); response.json = json; return response; }; fetch('https://jsonplaceholder.typicode.com/todos/1') .then((response) => response.json()) .then((json) => console.log(json)); // log // { // "userId": 1, // "id": 1, // "title": "Intercepted: delectus aut autem", // "completed": false // }
在上面的代碼中,我們更改了 json
方法以返回一些自定義數(shù)據(jù)來替代原始數(shù)據(jù)。查看文檔了解更多 可以更改的屬性。
注意: response
只允許使用一次。因此,每次需要使用 response
時(shí),都需要 克隆 response。
錯(cuò)誤處理
通過檢查 response.ok
和 response.status
的值,可以很容易地處理請(qǐng)求的錯(cuò)誤。在下面的代碼片段中,可以攔截 404 錯(cuò)誤
const { fetch: originalFetch } = window; window.fetch = async (...args) => { let [resource, config] = args; let response = await originalFetch(resource, config); if (!response.ok && response.status === 404) { // 404 error handling return Promise.reject(response); } return response; }; fetch('https://jsonplaceholder.typicode.com/todos/1000000') .then((response) => response.json()) .then((json) => console.log(json)) .catch((error) => console.error(error));
Node.js
你可以在 Node.js 中使用相同的方法。然而,Node.js 原生不支持 Fetch API (盡管對(duì) Fetch API 的原生支持將在 Node.js 的未來版本中提供)?,F(xiàn)在,你需要安裝 Node Fetch 包,然后對(duì) fetch
方法使用猴子補(bǔ)丁?!咀g:Node18已經(jīng)支持了!】
使用 fetch-intercept 庫(kù)
如果你不喜歡做這些 dirty
的事情(雙關(guān)語(yǔ)【譯:我也不懂指什么?】) ,那么 fetch-intercept 庫(kù)允許您使用更干凈的 API 注冊(cè)攔截器。您可以使用 npm 或 Yarn 來安裝這個(gè)庫(kù),如下所示:
npm install fetch-intercept whatwg-fetch --save // or yarn install fetch-intercept whatwg-fetch
注意: fetch-intercept 只支持瀏覽器,不能在 Node.js 中工作。因此,它還需要使用 whatwg-fetch 作為依賴項(xiàng)。
通過下面的代碼,我們可以實(shí)現(xiàn)與我們的猴子補(bǔ)丁示例相同的請(qǐng)求和響應(yīng)攔截器:
import * as fetchIntercept from 'fetch-intercept'; const unregister = fetchIntercept.register({ request: function (url, config) { const modifiedUrl = `https://jsonplaceholder.typicode.com/todos/2`; return [modifiedUrl, config]; }, requestError: function (error) { return Promise.reject(error); }, response: function (response) { const clonedResponse = response.clone(); const json = () => clonedResponse .json() .then((data) => ({ ...data, title: `Intercepted: ${data.title}` })); response.json = json; return response; }, responseError: function (error) { return Promise.reject(error); }, }); fetch('https://jsonplaceholder.typicode.com/todos/1') .then((response) => response.json()) .then((json) => console.log(json)); // unregister interceptors unregister();
register
方法允許你為 Fetch API 請(qǐng)求注冊(cè)攔截器。它接受一個(gè)帶有 request
, requestError
, response
, 和 responseError
回調(diào)的對(duì)象。register
方法返回另一個(gè)可用于注銷攔截器的方法。
Fetch API 本身不支持?jǐn)r截器。但是,還有其他支持?jǐn)r截器的 HTTP 請(qǐng)求庫(kù)??匆幌?Axios,它提供了開箱即用的功能。
總結(jié)
在本文中,我們介紹了什么是 JavaScript 攔截器,學(xué)習(xí)了如何通過給 Fetch API 使用猴子補(bǔ)丁和使用 fetch-intercept 庫(kù)來創(chuàng)建攔截器。
攔截器最初由 Angular 引入,對(duì)于各種各樣的用例都很有幫助,比如幫助處理全局錯(cuò)誤、身份驗(yàn)證、日志記錄等等。你可以使用本文描述的方法將攔截器添加到 JavaScript 應(yīng)用程序中,但是,請(qǐng)記住在 Node.js 需要添加額外的依賴。
以上就是JavaScript Fetch API請(qǐng)求和響應(yīng)攔截詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript Fetch API請(qǐng)求響應(yīng)攔截的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
利用CSS、JavaScript及Ajax實(shí)現(xiàn)高效的圖片預(yù)加載
圖片預(yù)加載想必大家都不陌生吧,實(shí)現(xiàn)預(yù)加載圖片有很多方法,包括使用CSS、JavaScript及兩者的各種組合。這些技術(shù)可根據(jù)不同設(shè)計(jì)場(chǎng)景設(shè)計(jì)出相應(yīng)的解決方案,十分高效2013-10-10JavaScript實(shí)現(xiàn)通過鍵盤彈鋼琴的效果實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于JavaScript實(shí)現(xiàn)通過鍵盤彈鋼琴效果的相關(guān)資料,通過JS代碼實(shí)現(xiàn)了鋼琴鍵盤的交互效果,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03webpack dll打包重復(fù)問題優(yōu)化的解決
在使用dll plugin過程中出現(xiàn)的一個(gè)包依賴問題,這個(gè)問題導(dǎo)致打出來的包會(huì)包含重復(fù)的代碼。這篇文章主要介紹了webpack dll打包重復(fù)問題優(yōu)化的解決,感興趣的小伙伴們可以參考一下2018-10-10JavaScript中字符串與Unicode編碼互相轉(zhuǎn)換的實(shí)現(xiàn)方法
這篇文章主要介紹了JavaScript中字符串與Unicode編碼互相轉(zhuǎn)換的實(shí)現(xiàn)方法涉及JavaScript編碼、數(shù)據(jù)類型等的轉(zhuǎn)換技巧,需要的朋友可以參考下2015-12-12數(shù)據(jù)庫(kù)管理工具PHPMyAdmin
這篇文章主要為大家介紹了數(shù)據(jù)庫(kù)管理工具PHPMyAdmin使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-095個(gè)javascript的數(shù)字格式化函數(shù)分享
Javascript沒有任何內(nèi)建的格式化函數(shù),這里我們通過Google收集了5個(gè)javascript的數(shù)字格式化函數(shù),希望對(duì)于大家的web開發(fā)能夠帶來方便2011-12-12JavaScript實(shí)現(xiàn)離開頁(yè)面前提示功能【附j(luò)Query實(shí)現(xiàn)方法】
這篇文章主要介紹了JavaScript實(shí)現(xiàn)離開頁(yè)面前提示功能,結(jié)合具體實(shí)例形式分析了javascript實(shí)現(xiàn)針對(duì)關(guān)閉頁(yè)面的事件響應(yīng)原理與操作技巧,并附帶jQuery的相應(yīng)實(shí)現(xiàn)方法,需要的朋友可以參考下2017-09-09微信小程序?qū)崿F(xiàn)視頻播放器發(fā)送彈幕
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)視頻播放器發(fā)送彈幕,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04Iframe 自動(dòng)適應(yīng)頁(yè)面的高度示例代碼
這篇文章主要介紹了Iframe如何自動(dòng)適應(yīng)頁(yè)面的高度,需要的朋友可以參考下2014-02-02