您如何挂钩使用Fetch Api的所有AJAX请求?以前我们可以做这样的事情来挂钩所有的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);
};
})();
或者更好的是,如果你想添加上面的函数,你将如何挂钩所有Fetch Api和所有XMLHttpRequest AJAX请求?
答案 0 :(得分:1)
事实上,本地浏览器支持获取 Api,并且只有一个界面:fetch
。
构造函数返回一个 Promise ,当您想要返回Promise以重写fetch的构造函数时,您无法获得Request
,Response
。
以下代码效果不佳。
(function() {
var oldFectch = fetch;
fetch.consotructor = function() {
return new Promise(resolve, reject) {
// your hook code
};
};
})();
那么,这是否意味着我们无法挂钩所有Fetch Api?的 NO!强>
首先,感谢window.fetch polyfill。
然后,让我们做点什么(编辑fetch.js)并摇滚。
(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,
// ...
最后,把所有事情都勾起来作为你的更好!
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))
}
// ...
答案 1 :(得分:0)
由于承诺的性质,这很容易做到:
var taperFunction = response => response;
var originalFetch = fetch;
fetch = (input, init) => originalFetch(input, init)
.then(response => new Promise((resolve) => {
resolve(taperFunction(response));
}));
和更复杂(显式)的示例:
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);
});
});
});
};
答案 2 :(得分:0)
使用 async
和 await
,非常简单:
const oldFetch = window.fetch
window.fetch = async (input, options) => {
return await oldFetch(input, options)
}
示例:
const oldFetch = window.fetch
window.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())