Capture all Fetch Api AJAX requests

Is there a way to intercept all AJAX requests using the Fetch API? In the past, we were able to do this with XMLHttpRequest by implementing code similar to the following:

(function() {
    var origOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
      console.log('request started!');
      this.addEventListener('load', function() {
          console.log('request completed!');
          console.log(this.readyState); //always 4 (successful ajax completion)
          console.log(this.responseText); //response data
      });
      origOpen.apply(this, arguments);
    };
  })();

If you wanted to enhance the above approach, how would you intercept both Fetch API and XMLHttpRequest AJAX requests?

Answer №1

Here is a simple example showcasing how promises work:

var taperFunction = response => response;
var originalFetch = fetch;
fetch = (input, init) => originalFetch(input, init)
    .then(response => new Promise((resolve) => {
        resolve(taperFunction(response));
    }));

For a more complex and explicit demonstration, consider the following code snippet:

var originalFetch = fetch;
fetch = (input, init) => {
    debugger; // perform any desired actions on the request or reject it immediately
    return originalFetch(input, init).then(response => {
        // It's possible to await an existing promise and wrap its result in a new one instead of creating a new Promise instance in the constructor
        return new Promise((resolve) => {
            response.clone() // invoking `json()` only once, but cloning does the trick
                .json()
                .then(json => {
                    debugger; // take any necessary actions on the response, even `resolve(new Response(body, options));`
                    resolve(response);
                });
        });
    });
};

Answer №2

Implementing the use of async and await is fairly straightforward:

const originalFetch = window.fetch
window.fetch = async (input, options) => {
    return await originalFetch(input, options)
}

Here's a practical example:

const originalFetch = window.fetch
window.fetch = async (input, options) => {
    // make changes to the request here
    console.log(input)

    let response = await originalFetch(input, options)

    // manipulate the response
    let content = await response.text()
    content = 'goodbye!'
    return new Response(content, {
        status: response.status,
        statusText: response.statusText,
        headers: response.headers
    })
}

console.log(await (await fetch('/hello')).text())

Answer №3

It's interesting to note that the Fetch API is natively supported by browsers and offers just one interface: fetch. The constructor returns a single Promise, making it impossible to access the Request or Response when attempting to customize the constructor.

The provided code snippet doesn't function as expected, leading to potential frustrations.

(function() {
    var oldFectch = fetch;
    fetch.consotructor = function() {
        return new Promise(resolve, reject) {
            // your hook code
        };
    };
})();

However, this does not imply that all aspects of the Fetch API cannot be customized. There are ways to achieve this!

Firstly, acknowledgment goes to the window.fetch polyfill.

Next, by making modifications in fetch.js, we can proceed with our desired changes.

(function(self) {
    'use strict';

    // comment or delete the following code block
    // if (self.fetch) {
    //    return
    // }

    var support = {
        searchParams: 'URLSearchParams' in self,
        iterable: 'Symbol' in self && 'iterator' in Symbol,
        // ...

Lastly, feel free to customize everything to suit your preferences!

self.fetch = function(input, init) {
  return new Promise(function(resolve, reject) {
    var request = new Request(input, init)
    var xhr = new XMLHttpRequest()

    // Make necessary tweaks here!
    // Gain access to the XMLHttpRequest Object
    // Customize as required!

    xhr.onload = function() {
      var options = {
        status: xhr.status,
        statusText: xhr.statusText,
        headers: parseHeaders(xhr.getAllResponseHeaders() || '')
      }
      options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
      var body = 'response' in xhr ? xhr.response : xhr.responseText
      resolve(new Response(body, options))
    }
    // ...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Incorporating an external TypeScript script into JavaScript

If I have a TypeScript file named test.ts containing the code below: private method(){ //some operations } How can I access the "method" function within a JavaScript file? ...

Image carousel with variable height

I'm attempting to implement a slide show of images with previous and next functionality. When the user clicks "previous," I want the images to slide to the left, and when they click "next," I want the images to slide to the right with a 0.5 second del ...

Utilizing Stripe for Payment Processing

I'm encountering a problem with getting Stripe charging to function properly. Despite having manually loaded Composer since it wouldn't install, I am not receiving any PHP errors and the token creation is running smoothly. There don't seem t ...

Content not being displayed in Rails 4 with AJAX using Bootstrap 3 Modal

Despite researching several resources on BS modals with AJAX, such as the one found here: Bootstrap Modal in Rails Keeps displaying the first record, I am still encountering issues. Upon implementing AJAX (using JQuery 2.1.1), the modal successfully opens ...

Check if an element possesses a specific property and corresponding value in JavaScript

I was looking to determine if an object has a specific property with a certain value, and wanted to search for it within an array of objects. var test = [{name : "joey", age: 15}, {name: "hell", age: 12}] After testing the code snippet below, I realized ...

Create static HTML files using an Express server

Recently, I developed a nodejs web project using express-js and ejs. However, upon further reflection, it occurred to me that hosting it as static html files on Netlify might be more cost-effective than running it as a nodejs app on Heroku. Since the data ...

How to access the onchange text in a react-select search component

I'm currently working on implementing search select functionality in my webpage using the react-select-search npm package. This is my main component: import React, { Component } from "react"; import Task from "./task"; // Rest of ...

Is there a way to eliminate the legend symbol for just one legend in Highcharts?

Looking to customize a legend in Highcharts but facing limitations due to Plot Lines and Bands not having legends. To work around this, I have added an empty series that acts as a toggle for showing/hiding plot lines. Since my plot lines are vertical, I im ...

Refreshing an iframe located on disparate domains

There is a webpage called "main.jsp" within the domain "domain1". This page contains an iframe that loads content from another domain known as "domain2". Essentially, "main.jsp" serves as a common content platform, with the iframe displaying content from v ...

Limit the number input to only allow values between 0 and 100

I am utilizing the Number input component from MUI, which includes Increment and Decrement buttons for adjusting numbers. Is there a method to limit the input to only accept values ranging from 0 to 100 ? Additionally, how can I decrease the width of the ...

The process of uploading a file through ajax results in it being sent to php://input

---Resolved By making the following adjustment: var request = new XMLHttpRequest(); request.open("POST", $(this).attr('action')); request.send(formData); The issue is now fixed, but I am unsure of the underlying reason. I have not found an exp ...

Create a "load additional data" button

I'm working on building my blog and I've run into a roadblock while trying to implement a load more button. Here's what I currently have: actions: { LOAD_ARTICLE_LIST: function ({ commit }) { axios.get('someurl/articles') ...

Having difficulty removing new or existing lines on StackBlitz

I attempted to experiment with React on StackBlitz, but I encountered a problem where I couldn't delete any lines of code. It seems that while I can add new lines of code, deleting them is not an option. Even when logging in with GitHub, the issue per ...

Refreshing webpage content by utilizing iframes

I am looking for a way to completely clear a webpage using either Javascript or PHP. However, there seems to be an issue with a specific area of the page that is marked as: data-form="manual iframe" When attempting to clear the page, only the data within ...

Modifying a Json file in a Node application, while retaining the previously stored data

In my node script, I have a simple process where I update the db.json file via a form. The file is successfully updated, but when I try to render it in response for a GET or POST request, it only shows the previous results. var cors = require('cors&ap ...

How can an Embedded React + JSS component safeguard generic elements such as <button> and <p> from being affected by the page's style?

I am facing a challenge with a React component that is being embedded in various webpages, either through an extension or as a third-party tool. Most of the styling for this component is done using JSS, ensuring unique class names that cannot be overridde ...

Looking for assistance with the AJAX flow

I stumbled upon this diagram and I have some questions about it. Can you explain what the Raise - > DOM Event does? Why is a callback function created after creating an XMLHTTPRequest? What is the purpose of registering a callback in the process? How do ...

send back the result to the primary function

I need help with this code. I'm trying to return the budget from callbacks in the main function. How can I return a value from the main function? // This method returns the current budget of the user getCurrentBudget: function (req) { var reqTok ...

Sending data from an AJAX request to a Spring controller is a common task in web

var TableDatatablesEditable = function () { var handleTable = function () { function restoreRow(oTable, nRow) { var aData = oTable.fnGetData(nRow); var jqTds = $('>td', nRow); for (var i = 0, ...

The HTML element failed to be inserted

Currently, I am involved in a project based on .NET Core for my organization. This project entails loading work orders from our SQL database using Entity Framework and then filtering them to display as markers on a map via the Google Maps API for our insta ...