挂钩所有Fetch Api AJAX请求

时间:2017-06-23 19:31:08

标签: javascript ajax fetch-api

您如何挂钩使用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请求?

3 个答案:

答案 0 :(得分:1)

事实上,本地浏览器支持获取 Api,并且只有一个界面:fetch。 构造函数返回一个 Promise ,当您想要返回Promise以重写fetch的构造函数时,您无法获得RequestResponse

以下代码效果不佳。

(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)

使用 asyncawait,非常简单:

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())