JavaScript?中如何攔截全局?Fetch?API?的請求和響應(yīng)問題
本文翻譯自 Intercepting JavaScript Fetch API requests and responses
攔截器是可用于預(yù)處理或后處理 HTTP 請求的代碼塊,有助于全局錯(cuò)誤處理、身份驗(yàn)證、日志記錄等。在本文中,你將學(xué)習(xí)如何攔截 JavaScript Fetch API 請求。
攔截 HTTP 請求一般有兩種事件:請求和響應(yīng)事件。請求攔截器應(yīng)該在發(fā)送實(shí)際 HTTP 請求之前執(zhí)行,而響應(yīng)攔截器應(yīng)該在到達(dá)發(fā)出請求的應(yīng)用程序代碼之前執(zhí)行。
在深入研究代碼之前,我們需要了解一些重要的事情。首先,Fetch API 本身不支持?jǐn)r截器。其次,在 Node.js 中使用 Fetch API 需要額外的包。
JavaScript Fetch API
首先,讓我們介紹一些 Fetch API 的基礎(chǔ),例如語法:
const fetchResponsePromise = fetch(resource [, init])
resource 定義要獲取的資源,該資源可以是 Request 對象,也可以是 URL。init 是一個(gè)可選對象,它將包含你想應(yī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 請求的示例:
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 請求必須有 body。 查看 Fetch 文檔 了解更多詳細(xì)信息。
實(shí)現(xiàn)攔截
有兩種方法可以在 Fetch API 請求時(shí)添加攔截器:使用猴子補(bǔ)丁或者使用庫 fetch-intercept。
對 Fetch 使用猴子補(bǔ)?。╩onkey patching)
為任何 JavaScript 函數(shù)或方法創(chuàng)建攔截器的一種方法是對其進(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)建請求和響應(yīng)攔截器。
請求攔截器
在下面的示例中,我們將創(chuàng)建一個(gè)簡單的請求攔截器,用于更改一個(gè)請求示例的 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 請求將從 https://jsonplaceholder.typicode.com/todos/2 獲取數(shù)據(jù),而不是 https://jsonplaceholder.typicode.com/todos/1,并展示 ID 為 2 的 todo 數(shù)據(jù)。
注意: 請求攔截器最常見的用例之一是更改身份驗(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 的值,可以很容易地處理請求的錯(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 (盡管對 Fetch API 的原生支持將在 Node.js 的未來版本中提供)?,F(xiàn)在,你需要安裝 Node Fetch 包,然后對 fetch 方法使用猴子補(bǔ)丁。【譯:Node18已經(jīng)支持了!】
使用 fetch-intercept 庫
如果你不喜歡做這些 dirty 的事情(雙關(guān)語【譯:我也不懂指什么?】) ,那么 fetch-intercept 庫允許您使用更干凈的 API 注冊攔截器。您可以使用 npm 或 Yarn 來安裝這個(gè)庫,如下所示:
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ǔ)丁示例相同的請求和響應(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 請求注冊攔截器。它接受一個(gè)帶有 request, requestError, response, 和 responseError 回調(diào)的對象。register 方法返回另一個(gè)可用于注銷攔截器的方法。
Fetch API 本身不支持?jǐn)r截器。但是,還有其他支持?jǐn)r截器的 HTTP 請求庫??匆幌?nbsp;Axios,它提供了開箱即用的功能。
總結(jié)
在本文中,我們介紹了什么是 JavaScript 攔截器,學(xué)習(xí)了如何通過給 Fetch API 使用猴子補(bǔ)丁和使用 fetch-intercept 庫來創(chuàng)建攔截器。
攔截器最初由 Angular 引入,對于各種各樣的用例都很有幫助,比如幫助處理全局錯(cuò)誤、身份驗(yàn)證、日志記錄等等。你可以使用本文描述的方法將攔截器添加到 JavaScript 應(yīng)用程序中,但是,請記住在 Node.js 需要添加額外的依賴。
到此這篇關(guān)于JavaScript 中如何攔截全局 Fetch API 的請求和響應(yīng)問題的文章就介紹到這了,更多相關(guān)js攔截全局Fetch API內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)刷新不重記的倒計(jì)時(shí)
網(wǎng)上關(guān)于JavaScript實(shí)現(xiàn)倒計(jì)時(shí)的文章有很多,但是一般都是刷新后會重新開始計(jì)時(shí),可是我們有的時(shí)候會需要刷新卻不重新計(jì)算的倒計(jì)時(shí),這該怎么做呢?下面我們一起來看看這種倒計(jì)時(shí)怎么實(shí)現(xiàn)吧。2016-08-08
javascript多行字符串的簡單實(shí)現(xiàn)方式
之前我們給大家講訴過javascript多行字符串的7種解決辦法,今天來給大家分享一個(gè)更簡單的方法,非常的實(shí)用,大家一定要仔細(xì)看看哦。2015-05-05
javascript設(shè)計(jì)模式 – 適配器模式原理與應(yīng)用實(shí)例分析
這篇文章主要介紹了javascript設(shè)計(jì)模式 – 適配器模式,結(jié)合實(shí)例形式分析了javascript適配器模式相關(guān)概念、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04
javascript下arguments,caller,callee,call,apply示例及理解
在看到大家如此關(guān)注JS里頭的這幾個(gè)對象,我試著把原文再修改一下,力求能再詳細(xì)的闡明個(gè)中意義2009-12-12
基于BootStrap Metronic開發(fā)框架經(jīng)驗(yàn)小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理
在很多系統(tǒng)模塊里面,我們可能都需要進(jìn)行一定的數(shù)據(jù)交換處理,這樣可以很好的達(dá)到用戶操作體驗(yàn)感,接下來通過本文給大家介紹基于BootStrap Metronic開發(fā)框架經(jīng)驗(yàn)小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理相關(guān)知識,非常具有參考價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-05-05

