JavaScript에서 fetch() API 요청 및 응답 가로채기
JavaScript에서 fetch API 요청 및 응답을 가로채고 싶습니다.
예를 들어 요청을 보내기 전에 요청 URL을 가로채고 응답이 도착하면 가로채고 싶습니다.
아래 코드는 모든 응답을 가로채기 위한 것입니다.XMLHTTPRequest
s.
(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
약속하고 아마도 응답(논문, 읽기 등)으로 작업하지만, (작성 시) 불필요한 폐쇄성이 있고, 비파괴적으로 응답 본문을 읽는 방법을 보여주지 않는다.스택 오버플로를 일으키는 변수 에일리어싱 버그도 포함되어 있습니다.
이 답변은 지금까지 나온 답변 중 가장 완벽하지만 콜백에 관련 없는 잡음이 있으며, 요격자에 의해 시체를 수집하기 위한 응답 복제에 대해서는 언급하지 않았다.그것은 어떻게 모조품이 돌아올 수 있는지 설명해주지 않는다.
이러한 문제를 수정하는 최소한의 완전한 예를 다음에 나타냅니다.파라미터 로깅을 처리하는 방법, 응답을 복제하여 원래 발신자에게 피해를 주지 않고 본문을 읽는 방법, 그리고 (옵션으로) 모의 응답을 제공하는 방법을 보여 줍니다.
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))
;
fetch 요구와 파라미터를 대행 수신하기 위해 아래에 언급된 방법으로 진행할 수 있습니다.내 문제가 해결됐어
const constantMock = window.fetch;
window.fetch = function() {
// Get the parameter in arguments
// Intercept the parameter here
return constantMock.apply(this, arguments)
}
응답 본문을 가로채려면 새 Promise를 만들고 전류를 "그때" 코드로 해결하거나 거부해야 합니다.해결이 되었고, 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의 답변에 덧붙여, 여기 각 가져오기 요청 전후에 Redx에서 스피너 상태를 업데이트한 방법이 있습니다.
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;
})
}
})();
언급URL : https://stackoverflow.com/questions/45425169/intercept-fetch-api-requests-and-responses-in-javascript
'programing' 카테고리의 다른 글
React Hooks useState+useEffect+이벤트가 오래된 상태를 나타냄 (0) | 2023.04.05 |
---|---|
반응의 PropTypes.node와 PropTypes.any의 차이점은 무엇입니까? (0) | 2023.04.05 |
React의 인라인 CSS 스타일: 미디어 쿼리를 구현하는 방법 (0) | 2023.04.05 |
코드의 ASP.NET Core appsettings.json 업데이트 (0) | 2023.04.05 |
Json.NET: 중첩된 사전을 역직렬화하는 중 (0) | 2023.04.05 |