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}`);
}
要使用它,我们可以使用以下代码。
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));
})();
还没什么特别的。我们可以调用使用 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));
})();
让我们看看这里发生了什么。
我们创建一个代理处理程序来访问 apply 陷阱。
然后,我们不再执行请求,而是记录参数。
然后,我们代理 fetch 函数并应用我们的处理程序。
这样,我们就可以将其用作标准的 Fetch API 了!
最酷的部分是所有 Fetch 参数都保持不变,因此无需更改任何现有的实现格式。
现在让我们将其移到我们的函数中,以便能够在常规获取和代理获取之间切换!
我们首先必须在类中引入一个构造函数,它将定义我们应该使用哪种获取方法。
constructor(fetchMethod = (...args) => fetch(...args)) {
this.fetchMethod = fetchMethod;
}
此函数可以设置 fetch 方法及其所有参数。默认情况下,我们将其设置为fetch
。
然后我们可以修改现有的调用以使用首选的获取方法。
getTodos = async () =>
await this.fetchMethod('https://jsonplaceholder.typicode.com/todos');
如你所见,变化不大。我们迁移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));
})();
我们创建一个新的代理提取,在我们的例子中,控制台记录所有请求,然后返回完成。
然后我们将这个代理获取版本传递给我们的类,以便它使用这个。
欢迎在 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);
如你所见,这与我们在主文中看到的概念类似。
我们代理现有的 fetch 方法,但覆盖其执行的内容。
在此示例中,我们向浏览器运行时发送了一条消息。
结论
使用 Proxy 对象,我们可以代理现有的 API,例如 Fetch API。
这会变得非常强大,因为我们不必模拟整个函数,而是代理它来完成我们需要做的事情。
感谢您的阅读,让我们联系起来!
感谢您阅读我的博客。欢迎订阅我的电子邮件简报,并在Facebook或Twitter上与我联系。
文章来源:https://dev.to/dailydevtips1/javascript-proxy-the-fetch-api-p15