如何通过axios实现一个http请求库(译)

最近在阮一峰的一篇每周分享上看到了这篇文章,想翻译(第一次)一下,正好想借此研究一下axios这个大名鼎鼎的库。

原文链接https://www.tutorialdocs.com/article/axios-learn.html

概览

在我们做前端开发的时候,经常碰到需要异步请求的情况。当我们用一个强大而齐全的http请求库的话,可以大大降低开发成本,提高开发效率。

axios是近几年非常火的一个http请求库。现在Github已经有了超过40k的Star,并且被很多前端大牛推荐。

因此,想要通过axios帮助我们实现一个http请求库之前必须要了解它的设计方式。在编写本文时,axios的版本为0.18.0,因此我们以这个版本为例来阅读和分析特定的源代码。axios的当前所有源文件都在lib文件夹中,因此下面的路径都是指lib文件夹的路径。

这里我们主要会谈及:

  • 如何使用axios
  • axios的核心模块(requests, interceptors, withdrawals)是如何设计实现的?
  • axios的设计有哪些优点?

如何使用axios

想要理解axios的设计,我们首先要了解一下如何使用它。让我们用一个简单的例子来了解axios的api。

发送请求

1
2
3
4
5
6
7
8
axios({
method:'get',
url:'http://bit.ly/2mTM3nY',
responseType:'stream'
})
.then(function(response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
});

这是一个官方的例子。从上面的代码上来看axios使用起来非常像jQueryajax,并且他们都返回一个Promise来继续下面的操作(在这里也能用成功回调函数,但是还是推荐Promise或者await)。

我不用解释这个简单的例子,我们再来看看怎么添加一个过滤器(filter)。

添加拦截器(interceptors

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Add a request interceptor. Note that there are 2 functions - one succeeds and one fails, and the reason for this will be explained later.
axios.interceptors.request.use(function (config) {
// The process before sending the request.
return config;
}, function (error) {
// Request error handling.
return Promise.reject(error);
});

// Add a response interceptor.
axios.interceptors.response.use(function (response) {
// Processing for the response data.
return response;
}, function (error) {
// Processing after the response error.
return Promise.reject(error);
});

从上面的代码我们可以看出:在发请求之前,我们能够拦截到config参数,并且可以对这个config进行一些处理;在请求回来之后,我们也可以对返回的数据进行一些通用处理。与此同时,我们也可以对requestresponse添加失败监听,来处理失败的情况。

取消HTTP请求

当我们开发搜索相关的模块的时候,我们需要经常发请求去查询。通常情况下,在我们发下一个请求的时候,我们需要把最后的请求给取消掉。因此,取消请求相关的方法也是一个优点。axios取消请求的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});

axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})

// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');

从上面的代码可以看出,axios使用的是基于CancelToken提出的撤销。然而,这个提案已经被撤销,详情请见这里;具体的取消方法的实现会在后面源码分析那部分进行解释。