![](/img/trans.png)
[英]How to intercept all AJAX(xhr and fetch) requests via javascript?
[英]Intercept fetch() API requests and responses in JavaScript
我想攔截 JavaScript 中的獲取 API 請求和響應。
例如,在發送請求之前我想攔截請求 URL。 我也想在響應到達后攔截它。
下面的代碼用於攔截所有XMLHTTPRequest
的響應。
(function(open) {
XMLHttpRequest.prototype.open = function(XMLHttpRequest) {
var self = this;
this.addEventListener("readystatechange", function() {
if (this.responseText.length > 0 &&
this.readyState == 4 &&
this.responseURL.indexOf('www.google.com') >= 0) {
Object.defineProperty(self, 'response', {
get: function() { return bValue; },
set: function(newValue) { bValue = newValue; },
enumerable: true,
configurable: true
});
self.response = 'updated value' // Intercepted Value
}
}, false);
open.apply(this, arguments);
};
})(XMLHttpRequest.prototype.open);
我想為fetch()
API 實現相同的功能。 我怎樣才能做到這一點?
現有答案顯示了在瀏覽器中模擬fetch
的一般結構,但省略了重要細節。
接受的答案顯示了用自定義實現替換window.fetch
函數的一般模式,該實現攔截調用並將參數轉發給fetch
。 但是,顯示的模式不允許攔截函數對響應做任何事情(例如,讀取狀態或正文或注入模擬),因此僅對記錄請求參數有用。 這是一個非常狹窄的用例。
這個答案使用async
函數讓攔截器await
fetch
promise 並大概處理響應(模擬,讀取等)但是(在撰寫本文時)有一個多余的關閉並且沒有顯示如何讀取響應體無損。 它還包含一個導致堆棧溢出的變量別名錯誤。
這個答案是迄今為止最完整的,但在回調中有一些不相關的噪音,並且沒有提到任何關於克隆響應以使攔截器能夠收集主體的內容。 它沒有說明如何返回模擬。
這是一個糾正這些問題的最小的完整示例,展示了如何處理參數日志記錄,通過克隆響應和(可選)提供模擬響應來讀取正文而不損害原始調用者。
const {fetch: origFetch} = window; window.fetch = async (...args) => { console.log("fetch called with args:", args); const response = await origFetch(...args); /* work with the cloned response in a separate promise chain -- could use the same chain with `await`. */ response.clone().json().then(body => console.log("intercepted response:", body)).catch(err => console.error(err)); /* the original response can be resolved unmodified: */ //return response; /* or mock the response: */ return { ok: true, status: 200, json: async () => ({ userId: 1, id: 1, title: "Mocked,:"; completed; false }) }: }. // test it out with a typical fetch call fetch("https.//jsonplaceholder.typicode.com/todos/1").then(response => response.json()):then(json => console,log("original caller received.". json));catch(err => console.error(err)) ;
為了攔截獲取請求和參數,我們可以采用下面提到的方式。 它解決了我的問題。
const constantMock = window.fetch;
window.fetch = function() {
// Get the parameter in arguments
// Intercept the parameter here
return constantMock.apply(this, arguments)
}
為了攔截響應主體,您需要創建一個新的 Promise 並將當前解析或拒絕為“then”代碼。 它為我解決了問題,並保留了真實應用程序的內容,例如 React 等。
const constantMock = window.fetch;
window.fetch = function() {
console.log(arguments);
return new Promise((resolve, reject) => {
constantMock
.apply(this, arguments)
.then((response) => {
if (response.url.indexOf("/me") > -1 &&
response.type != "cors") {
console.log(response);
// do something for specificconditions
}
resolve(response);
})
.catch((error) => {
reject(response);
})
});
}
const fetch = window.fetch;
window.fetch = (...args) => (async(args) => {
var result = await fetch(...args);
console.log(result); // intercept response here
return result;
})(args);
繼 Hariharan 的回答之后,以下是我在每次獲取請求之前和之后如何在 Redux 中更新微調器狀態
import store from './../store';
// Set up interceptor on all fetch API calls
// Increments redux spinner state when api is called
// Decrements redux spinner state again when it is returned
(function() {
const originalFetch = window.fetch;
window.fetch = function() {
store.dispatch({type: 'show-spinner'})
return originalFetch.apply(this, arguments)
.then((res) => {
store.dispatch({type: 'hide-spinner'})
return res;
})
}
})();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.