How would you hook all AJAX requests that use the Fetch Api? Previously we could do something like this to hook all XMLHttpRequest:
(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); //will always be 4 (ajax is completed successfully)
console.log(this.responseText); //whatever the response was
});
origOpen.apply(this, arguments);
};
})();
Or better yet, if you wanted to add to the function above, how would you hook all Fetch Api and all XMLHttpRequest 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))
}
// ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With