簡體   English   中英

在 JavaScript 中攔截 fetch() API 請求和響應

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM