我可以使用 axios 拦截器将 API 请求替换为本地存储数据吗?

Can I use axios interceptors to replace an API request with local storage data?

提问人:Aaron Parisi 提问时间:11/9/2023 最后编辑:PhilAaron Parisi 更新时间:11/10/2023 访问量:67

问:

我的应用程序中有一个带有一些拦截器的 api 客户端:

const api = new OpenAPIClientAxios({...})
const client = api.initSync()
client.interceptors.request.use(...)
client.interceptors.response.use(...)

我想编写一个请求拦截器,用于检查本地存储中的一些数据。如果数据存在,我根本不想发出请求,而只是使用本地存储数据进行响应。

这可能吗?还是我滥用了拦截器?

JavaScript Axios 本地存储 拦截器

评论


答:

1赞 Phil 11/9/2023 #1

拦截器只能用于操作请求和响应的配置。不幸的是,您不能完全绕过他们的请求。

Axios 确实提供了一个配置,该配置...adapter

允许自定义处理请求

使用它,您可以创建一个带有自定义的 Axios 实例,以拦截请求并使用本地数据提供响应。adapter

// mock localStorage
const localStorage = {s:{},setItem(k,v){this.s[k]=v},getItem(k){return this.s[k]??null}};
// mock OpenAPI client
const client = /* api.initSync() */ axios.create({ baseURL: "https://jsonplaceholder.typicode.com/" });

const wrapper = axios.create({
  adapter: ({ adapter, ...config }) => {
    const data = JSON.parse(localStorage.getItem("data"));
    if (data) {
      // return a valid response
      return Promise.resolve({
        data,
        config,
        status: 200,
      });
    }
    
    // otherwise pass-through to the real client
    return client(config);
  }
});

(async () => {
  // with no data present
  console.log("no local data:", (await wrapper.get("/todos/1")).data);

  // with local data
  localStorage.setItem("data", JSON.stringify({ foo: "FOO" }));
  console.log("with local data:", (await wrapper.get("/todos/1")).data);
})();
.as-console-wrapper { max-height: 100% !important; }
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>

评论

0赞 Aaron Parisi 11/10/2023
这可以在通过开放 api 客户端 axios 的 initSync 方法创建的 axios 客户端上使用吗?
0赞 Aaron Parisi 11/10/2023
另外,您认为适配器 fn 可以返回 Promise 或客户端?
0赞 Phil 11/10/2023
@AaronParisi 1) 是的,只要客户端实际上是 Axios 实例。2)它不是返回,而是返回一个返回承诺的呼叫clientclient()
0赞 Aaron Parisi 11/10/2023
是有道理的 - 我在浏览器中收到无限请求的循环,但会搞砸它,我认为您的答案是正确的
1赞 Phil 11/10/2023
@AaronParisi确保在函数参数中使用。您想要从直通请求中提取{ adapter, ...config }adapteradapter
2赞 Eric MORAND 11/9/2023 #2

我想提出另一种方法:你可以编写一个函数来抽象数据的检索,而不是向 axios 添加拦截器,它将:

  • 检查本地数据并返回找到的数据(如果有)
  • 否则执行远程调用

换句话说,编写一个域服务/存储库。