JavaScript 代理 Fetch API

2025-06-04

JavaScript 代理 Fetch API

如果您继续在谷歌上搜索 JavaScript Proxy,您会看到许多解释核心概念的文章。

但几乎没人会告诉你一件很强大的事。
那就是:

您可以使用代理来覆盖现有的 API!

我知道这很有道理。它可以扩展任何对象、数组或函数,所以这是合乎逻辑的。但让我用一个实际的例子来解释一下,在这个例子中我使用了 Proxy 对象。

使用代理扩展 Fetch API

您听说过Fetch API,它是一个高效执行 URL 请求的本机包装器。

假设我们的应用程序有一个处理所有 API 调用的文件,并且它们都使用 Fetch API。

例如,我们有以下类来处理 Todos 的 API 调用。

class TodoAPI {
  getTodos = async () =>
    await fetch('https://jsonplaceholder.typicode.com/todos');
  getTodo = async (id: number) =>
    await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
}
Enter fullscreen mode Exit fullscreen mode

要使用它,我们可以使用以下代码。

const API = new TodoAPI();

(async () => {
  await API.getTodos()
    .then((data) => data.json())
    .then((res) => console.log(res));
  console.log('Fetching single TODO');
  await API.getTodo(3)
    .then((data) => data.json())
    .then((res) => console.log(res));
})();
Enter fullscreen mode Exit fullscreen mode

还没什么特别的。我们可以调用使用 fetch 请求的 API 中间件。

这段代码在我们的网站上运行良好,但当我们将其引入 Chrome 扩展程序时,我们很快发现无法直接使用 fetch 方法。CORS
问题阻碍了我们将其注入到其他网站。

我们仍然应该接受所有 Fetch 请求数据,但通过后台工作者发送。

所以一个想法是创建一个模拟 Fetch API 的新函数,这个方法应该可行。
但是,当 Fetch API 的 props 发生变化时会发生什么呢?

因此解决这个问题的更好方法是利用代理对象!

是的,我们可以代理 Fetch API。

在一个非常简单的例子中,它看起来像这样:

(async () => {
  const fetchHandler = {
    apply(target, thisArg, args) {
      console.log(args);
    },
  };

  const proxiedFetch = new Proxy(fetch, fetchHandler);

  await proxiedFetch('https://jsonplaceholder.typicode.com/todos/3')
    .then((data) => data.json())
    .then((res) => console.log(res));
})();
Enter fullscreen mode Exit fullscreen mode

让我们看看这里发生了什么。
我们创建一个代理处理程序来访问 apply 陷阱。
然后,我们不再执行请求,而是记录参数。

然后,我们代理 fetch 函数并应用我们的处理程序。
这样,我们就可以将其用作标准的 Fetch API 了!

最酷的部分是所有 Fetch 参数都保持不变,因此无需更改任何现有的实现格式。

现在让我们将其移到我们的函数中,以便能够在常规获取和代理获取之间切换!

我们首先必须在类中引入一个构造函数,它将定义我们应该使用哪种获取方法。

constructor(fetchMethod = (...args) => fetch(...args)) {
    this.fetchMethod = fetchMethod;
}
Enter fullscreen mode Exit fullscreen mode

此函数可以设置 fetch 方法及其所有参数。默认情况下,我们将其设置为fetch

然后我们可以修改现有的调用以使用首选的获取方法。

getTodos = async () =>
  await this.fetchMethod('https://jsonplaceholder.typicode.com/todos');
Enter fullscreen mode Exit fullscreen mode

如你所见,变化不大。我们迁移fetch.到了this.fetchMethod.,并且所有 props 和回调都保持不变。

但是,该示例仍然使用常规的旧提取。

让我们设置一个新版本来使用自定义代理获取。

const proxyFetch = {
  apply(_, __, args) {
    console.log(args);
    return { message: 'proxy done' };
  },
};
const proxiedFetch = new Proxy(fetch, proxyFetch);

const API = new TodoAPI(proxiedFetch);

(async () => {
  await API.getTodos().then((res) => console.log(res));
  console.log('Fetching single TODO');
  await API.getTodo(3).then((res) => console.log(res));
})();
Enter fullscreen mode Exit fullscreen mode

我们创建一个新的代理提取,在我们的例子中,控制台记录所有请求,然后返回完成。

然后我们将这个代理获取版本传递给我们的类,以便它使用这个。

欢迎在 CodePen 上尝试一下。您可以切换为传递代理获取或留空。

后台工作者示例

我描述了一个扩展的后台工作示例,我们模拟获取请求以通过浏览器运行时消息发送它收到的所有请求。

代码如下:

const proxyFetch = {
  apply(_, __, args) {
    browser.runtime.sendMessage({
      type: 'FETCH_REQUEST',
      url: args[0],
      args: args[1],
    });
    return null;
  },
};

export const proxiedFetch = new Proxy(fetch, proxyFetch);
Enter fullscreen mode Exit fullscreen mode

如你所见,这与我们在主文中看到的概念类似。
我们代理现有的 fetch 方法,但覆盖其执行的内容。
在此示例中,我们向浏览器运行时发送了一条消息。

结论

使用 Proxy 对象,我们可以代理现有的 API,例如 Fetch API。

这会变得非常强大,因为我们不必模拟整个函数,而是代理它来完成我们需要做的事情。

感谢您的阅读,让我们联系起来!

感谢您阅读我的博客。欢迎订阅我的电子邮件简报,并在FacebookTwitter上与我联系。

文章来源:https://dev.to/dailydevtips1/javascript-proxy-the-fetch-api-p15
PREV
JavaScript 在窗口之间发送数据
NEXT
JavaScript 检查对象中是否存在属性