首页
Preview

在应用程序中为所有 HTTP 调用设置 Axios 拦截器

随着互联网的成熟和复杂化,收集数据进行复杂处理也变得更加复杂了。

想想看:在互联网刚刚兴起的时候,你只能发送和接收电子邮件,通过关键词搜索信息,并访问一些极其基础的网站。而今天,你可以:订一辆车,并让它在几分钟内在你的准确位置接你,使用存储在手机上的信用卡号进行购物,通过语音搜索极其具体的问题,并获得数千个有用且相关的答案。现在我们只需花费很少的精力就可以轻松获取到想要的信息。

随着互联网对我们作为用户变得更加有用,对于我们作为开发者来说,获取所需数据的难度也在增加,这就是我今天要讲述的故事。

作为一名软件工程师,我处理的绝大部分数据都存储在应用程序和数据库之外的某个地方。因此,我需要花费大量时间通过HTTP调用从自己之外的应用程序请求数据、接收数据、验证数据、重新塑形数据等。

很多时候,这些HTTP调用并不是那么简单的:我不能只发送一个GET或者POST请求并期望得到200响应。这些HTTP调用需要cookies、授权令牌、安全头、JWT、API密钥或其他验证方法——我请求数据的团队需要知道我的应用程序有权与他们负责的信息进行交互。

这是完全合理的,而且现在也很正常;系统需要证明它们有权查看或更改数据。这些数据不能随便让任何拥有互联网连接且知道其服务URL的人都能访问,那样可能非常危险。

但尽管这是正常的,确保每个HTTP请求或响应都具有通过验证所需的所有信息可能非常重复且容易忘记添加。但这并不是必须的。通过流行的JavaScript HTTP客户端Axios的帮助,你可以设置拦截器函数以捕获每个HTTP请求或响应,并执行任何需要进行的操作,而无需你考虑太多——这是最好的解决方案。

提示:使用BitGithub)在项目之间共享可重用组件。

Bit使独立组件之间的共享、文档编写和重用变得简单。使用它来最大程度地提高代码重用率、保持一致的设计、团队协作、加速交付和构建可扩展的应用程序。

Bit支持Node、TypeScript、React、Vue、Angular等。

Bit.dev上探索共享组件

认识Axios

如果你还不熟悉它,那么Axios是一个非常流行的基于Promise的JavaScript HTTP客户端,适用于浏览器和服务器端的Node.js。

除了你期望从任何HTTP客户端获得的基本CRUD(创建、读取、更新、删除)功能外,Axios默认还提供了许多其他有用的功能,如:配置默认值、错误处理、请求取消、自动将JavaScript对象序列化为JSON等等,但我今天想要重点介绍的是Axios的拦截器。

Axios拦截器

拦截器是一种允许应用程序在.then().catch()处理请求或响应之前拦截请求或响应的功能。

你会问这有什么帮助?嗯,正如我上面提到的那样,假设每个HTTP请求都需要附加一个header属性,以便验证请求数据的应用程序是否有权访问该数据。或者假设,有时HTTP响应会是错误的响应——一个400或500状态。在这些情况下,你可能希望自动重试请求,或者验证被拒绝的授权是否仍然有效。

Axios使设置拦截器变得非常容易,并且从我个人的经验来看,无论拦截器在项目文件的哪个位置,它们似乎都能正常工作。让我们来看一些拦截器的示例。

拦截请求

我将展示的第一个代码示例是如何设置Axios的请求拦截器。该示例是在React应用程序内编写的,但我期望无论你使用哪个JavaScript框架(或不使用框架),该过程都应该类似。

两种类型的Axios拦截器都接受两个函数。请求拦截器的第一个函数在请求是有效的、成功的请求时修改请求,第二个函数在请求无效并抛出错误时处理请求。

这个特定的代码位于React应用程序的根目录中,位于src/文件夹中的index.js文件中。

index.js

Axios请求拦截器示例,如果将要请求特定的URL,则附加用户的用户名头。在上面的例子中,axios通过ES6 import语法在文件顶部导入,然后就可以使用了。我在示例中使用了ES6箭头函数,但它可以转换为基本的JavaScript:

axios.interceptors.request.use(
  function(successfulReq) {
    ...modify code; return successfulReq;
  }, 
  function(error) {
    ...return Promise.reject(error);
  }
);

在服务器端应用程序发送出站HTTP请求之前,对request进行必要的处理。

这个特定的拦截器的目的是:每当应用程序向其中一个支持服务之一发出HTTP请求,其中包括checkoutbillingorder的URL时,Axios会自动将一个header附加到请求中,其中包含存储在状态中的username。在我的情况下,Redux在状态中保存用户的信息,但它也可以存储在本地存储、会话存储中,无论哪种方式都可以。

如果HTTP请求不是要发送到这些服务之一,拦截器就不会修改请求,而是让其按原样继续前进。

如果请求出现错误,第二个函数error()函数将会启动并抛出一个错误,拒绝请求并给出原因。

不太复杂,对响应进行拦截也可以非常简单。

拦截响应

我有两个响应拦截器的示例要展示给你,因为这两个示例都很有用,而且这两个示例发生在应用程序的不同部分:一个在浏览器中的客户端,另一个在服务器端——Node.js端。

与请求拦截器一样,响应拦截器接受两个函数参数:第一个函数是当响应返回的是一个200状态的HTTP响应时调用,第二个函数是当它是一个不在200范围内的状态码时调用。当我通过下面的示例进行说明时,这将更有意义。

客户端示例

第一个示例仍然位于我的React应用程序的根目录附近,但它不在请求拦截器的同一文件中,而是在src/文件夹中的App.js文件中。

App.js

在React部分的应用程序中,如果收到401未经授权的HTTP响应,检查用户浏览器凭据是否仍然有效的请求拦截器示例。

由于这是在应用程序的React部分中,因此在文件顶部导入了Axios库:import axios from 'axios';,然后使用以下方式调用请求拦截器:

axios.interceptors.response.use(
  function(successRes) {
    ... modify response; 
    return successRes;
  }, 
  function(error) {
    ... return Promise.reject(error);
  }
);

我的特定示例仅在从服务接收到401未经授权的错误的HTTP响应时发生,因此传递给响应拦截器的第一个参数是undefined。如果响应是任何类型的200响应,Axios拦截器不会关心它。

但是,如果HTTP响应是401,则我的第二个函数(axiosRetryInterceptor()函数)会启动,并检查登录用户的凭据是否仍然有效——因为401表示用户的授权令牌、cookie或会话可能已过期。如果用户的会话确实已过期,则isUserValid()函数将最终将用户从应用程序中注销并要求他们重新登录,否则isUserValid()将返回不是401的原因,用户可以继续其会话。

因此,这是客户端上的一个Axios响应拦截器示例,现在让我们看一个服务器端的示例。

服务器端示例

第二个响应拦截器发生在应用程序的服务器端,并使用CommonJS样式的导入:

const axios = require('axios');

一旦使用require语法实例化它,实际拦截器的使用方式与浏览器中的拦截器几乎相同。下面是一个响应拦截器,它位于Node.js服务器的根目录附近,位于server/文件夹中。

server.js

一个在Axios响应拦截器中记录正面响应并重试失败响应的服务器端示例。

这个特定的响应拦截器有两个函数。第一个匿名函数记录调用了哪个方法(GETPOST等)、调用了哪个微服务(checkoutorders等)以及发出了哪个成功响应状态(200204等)。

第二个函数axiosRetryInterceptor()在接收到除200以外的HTTP状态时被调用。如果接收到400或500状态,此函数将重试原始请求,以期望获得某种200响应。它会重试最多3次,并且每次都会延长响应错误的服务之间的请求时间。

这有点复杂,因为backoff变量会延迟下一次尝试调用服务器,但这实际上就是这个响应拦截器所做的一切。

所以,这就是Axios请求和响应拦截器的精髓。实现起来并不困难,而且非常方便,你觉得呢?

注意:如果你的组件进行API调用,使用拦截器将错误处理、授权和请求预处理逻辑集中在一个地方是很有意义的。这将使你的组件脱离单体应用程序设计,使它们更易于重用、共享、维护和扩展。了解更多 这里

结论

今天的互联网很复杂,而且只会变得更加复杂。但是,对于我们Web开发人员来说,有一些很棒的JavaScript包可以帮助我们处理一些复杂性。

我今天关注的复杂性是由许多其他服务拥有我们的应用程序需要的数据而引起的。通常情况下,我们的应用程序需要发送某种证明,证明它们有权访问那些服务拥有的数据,或者它们需要知道如果其他服务拒绝它们的请求该怎么做,这就是Axios拦截器派上用场的地方。这些小函数会自动拦截每个出站 HTTP 请求或入站 HTTP 响应,如果请求或响应与拦截器设置的参数匹配,则会根据开发人员的需要修改这些负载。需要在每个请求中发送 auth 头?搞定。如果服务发送回 500 响应,需要重试请求?没问题。Axios 拦截器专门为这些场景而构建。

参考文献和更多资源:

译自:https://blog.bitsrc.io/setting-up-axios-interceptors-for-all-http-calls-in-an-application-71bc2c636e4e

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
一个人玩
先找到想要的,然后出发

评论(0)

添加评论