且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

拦截并更改ajax调用的结果

更新时间:2021-07-02 07:04:05

此方法的重要部分是 Object.defineProperty API。

The important part of this method is the Object.defineProperty API.

您不能使用对象分配来覆盖 this.responseText = {...};

You can't use object assignment to override, this.responseText = {...};

<button>send</button>

<script>
  const nativeOpen = XMLHttpRequest.prototype.open;
  const nativeSend = XMLHttpRequest.prototype.send;

  const proxiedOpen = function () {
    // Mount the URL that needs to be intercepted to the `XMLHttpRequest` object.
    if (arguments[1].includes('jsonplaceholder.typicode.com/todos/1')) this._url = arguments[1];
    nativeOpen.apply(this, arguments);
  };

  const proxiedSend = async function () {
    if (this._url) {
      // Make other requests, it can also be a fixed value.
      const data = await fetch('https://jsonplaceholder.typicode.com/todos/5').then(res => res.json());
      // The data of `todos/1` is rewritten as `todos/5`
      Object.defineProperty(this, 'responseText', { value: JSON.stringify(data), writable: false });
    }
    nativeSend.apply(this, arguments);
  };

  // Override native methods
  XMLHttpRequest.prototype.open = proxiedOpen;
  XMLHttpRequest.prototype.send = proxiedSend;

  document.querySelector('button').addEventListener('click', () => {
    const xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
      if (this.readyState == 4 && this.status == 200) {
        console.log(this.responseText); // Will get the data of `todos/5` instead of `todos/1`.
      }
    };
    xhttp.open('GET', 'https://jsonplaceholder.typicode.com/todos/1', true);
    xhttp.send();
  });
</script>