Hook all Fetch Api AJAX requests
It is easy to do due to nature of promises:
var taperFunction = response => response;var originalFetch = fetch;fetch = (input, init) => originalFetch(input, init) .then(response => new Promise((resolve) => { resolve(taperFunction(response)); }));
and a bit more complex(explicit) example:
var originalFetch = fetch;fetch = (input, init) => { debugger; // do what ever you want with request or reject it immediately return originalFetch(input, init).then(response => { // it is not important to create new Promise in ctor, we can await existing one, then wrap result into new one return new Promise((resolve) => { response.clone() // we can invoke `json()` only once, but clone do the trick .json() .then(json => { debugger; // do what ever you want with response, even `resolve(new Response(body, options));` resolve(response); }); }); });};
In fact, Fetch Api is supported by native browser and only has one interface: fetch
.The constructor return one Promise, and you can't get the Request
、Response
when you want to return your Promise to rewrite the fetch's constructor.
The following code doesn't work well.
(function() { var oldFectch = fetch; fetch.consotructor = function() { return new Promise(resolve, reject) { // your hook code }; };})();
So,Does it mean we can't hook all Fetch Api ? NO!
Firstly, thanks the window.fetch polyfill.
Then, let's do something(edit fetch.js) and rock.
(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, // ...
Last, hook every thing as your better!
self.fetch = function(input, init) { return new Promise(function(resolve, reject) { var request = new Request(input, init) var xhr = new XMLHttpRequest() // Here we go! // Now we get the XMLHttpRequest Object // Do what you want! 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)) } // ...
Using async
and await
, it's quite simple:
const oldFetch = window.fetchwindow.fetch = async (input, options) => { return await oldFetch(input, options)}
An example:
const oldFetch = window.fetchwindow.fetch = async (input, options) => { // modify the request here console.log(input) let response = await oldFetch(input, options) // modify 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())