0. 系列文章

1.使用Typescript重构axios(一)——写在最前面

2.使用Typescript重构axios(二)——项目起手,跑通流程

3.使用Typescript重构axios(三)——实现基础功能:处理get请求url参数

4.使用Typescript重构axios(四)——实现基础功能:处理post请求参数

5.使用Typescript重构axios(五)——实现基础功能:处理请求的header

6.使用Typescript重构axios(六)——实现基础功能:获取响应数据

7.使用Typescript重构axios(七)——实现基础功能:处理响应header

8.使用Typescript重构axios(八)——实现基础功能:处理响应data

9.使用Typescript重构axios(九)——异常处理:基础版

10.使用Typescript重构axios(十)——异常处理:增强版

11.使用Typescript重构axios(十一)——接口扩展

12.使用Typescript重构axios(十二)——增加参数

13.使用Typescript重构axios(十三)——让响应数据支持泛型

14.使用Typescript重构axios(十四)——实现拦截器

15.使用Typescript重构axios(十五)——默认配置

16.使用Typescript重构axios(十六)——请求和响应数据配置化

17.使用Typescript重构axios(十七)——增加axios.create

18.使用Typescript重构axios(十八)——请求取消功能:总体思路

19.使用Typescript重构axios(十九)——请求取消功能:实现第二种使用方式

20.使用Typescript重构axios(二十)——请求取消功能:实现第一种使用方式

21.使用Typescript重构axios(二十一)——请求取消功能:添加axios.isCancel接口

22.使用Typescript重构axios(二十二)——请求取消功能:收尾

23.使用Typescript重构axios(二十三)——添加withCredentials属性

24.使用Typescript重构axios(二十四)——防御XSRF攻击

25.使用Typescript重构axios(二十五)——文件上传下载进度监控

26.使用Typescript重构axios(二十六)——添加HTTP授权auth属性

27.使用Typescript重构axios(二十七)——添加请求状态码合法性校验

28.使用Typescript重构axios(二十八)——自定义序列化请求参数

29.使用Typescript重构axios(二十九)——添加baseURL

30.使用Typescript重构axios(三十)——添加axios.getUri方法

31.使用Typescript重构axios(三十一)——添加axios.all和axios.spread方法

32.使用Typescript重构axios(三十二)——写在最后面(总结)

项目源码请猛戳这里!!!

1. 前言

在之前的文章中,虽然我们已经实现了axios的基本功能,但是那些都是正常情况,我们知道,在实际开发中,不可能没有错误发生。所以,接下来我们需要对一些常见的错误情况进行异常捕获和处理。我们期望,当异常出现时,我们都可以在 reject 回调函数中捕获到,如下形式:

axios({
method: 'get',
url: '/api/handleError'
}).then((res) => {
console.log(res)
}).catch((e) => {
console.log(e)
})

2. 需求分析

首先我们先来分析下一些常见的请求异常:

  • 网络异常,当网络不通时抛出的异常;
  • 请求超时,当请求发出后在指定时间内没有收到响应时抛出的异常。
  • 状态码非200-300异常,当请求的状态码不在200-300之间时,我们也认为它出现了异常;

OK,接下来,我们就对上面所列出的三种异常进行分别处理。

3. 异常处理

3.1 网络异常

当网络出现异常(比如不通)的时候发送请求会触发 XMLHttpRequest 对象实例的 error 事件,于是我们就可以在 onerror 的事件回调函数中捕获此类错误。

我们在 src/xhr.ts 中的xhr函数中添加如下代码:

// 4.1 网络错误事件
request.onerror = function() {
reject(new Error("Net Error"));
};

3.2 请求超时

在官方axios中,它允许用户在发请求时配置请求的超时时间timeout,也就是当请求发送后超过某个时间后仍然没收到响应,则请求自动终止,并会触发 XMLHttpRequest 对象实例的 ontimeout 事件。

1.首先,我们也要允许用户在发请求时可配置超时时间,所以我们在之前写好的请求参数接口类型AxiosRequestConfig里添加timeout选项,如下:

// src/types/index.ts

export interface AxiosRequestConfig {
url: string;
method?: Method;
headers?: any;
data?: any;
params?: any;
responseType?: XMLHttpRequestResponseType;
timeout?: number;
}

2.接着,在src/xhr.ts中的xhr函数中获取用户配置的timeout,如果该参数不为空,则将其设置到 XMLHttpRequest 对象实例request上。

const {data = null,url,method = "get",headers,responseType,timeout} = config;
if (timeout) {
request.timeout = timeout;
}

3.最后,我们通过注册 XMLHttpRequest 对象实例的 ontimeout 事件来捕获请求超时异常。

request.ontimeout = function() {
reject(new Error(`Timeout of ${timeout} ms exceeded`));
};

3.3 非200-300状态码

对于一个正常的请求,往往会返回 200-300 之间的 HTTP 状态码,对于不在这个区间的状态码,我们也把它们认为是一种错误的情况做处理。

1.首先,我们先在xhr函数中的onreadystatechange 的回调函数中,添加了对 request.status 的判断,因为当出现网络错误或者超时错误的时候,该值都为 0。

if (request.status === 0) {
return;
}

2.然后,我们再判断状态码是否在200-300之间,来决定是否抛出异常。

我们编写一个辅助函数handleResponse,如果状态码response.status在200-300之间,则 resolve(response),否则reject

function handleResponse(response: AxiosResponse): void {
if (response.status >= 200 && response.status < 300) {
resolve(response);
} else {
reject(new Error(`Request failed with status code ${response.status}`));
}
}

OK,三种异常处理就已经写完了,接下来我们就可以编写demo,来测试下效果如何。

4. demo编写

examples 目录下创建 handleError目录,在 handleError目录下创建 index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>handleError demo</title>
</head>
<body>
<script src="/__build__/handleError.js"></script>
</body>
</html>

接着再创建 app.ts 作为入口文件:

import axios from "../../src/index";

// 1.正常情况
axios({
method: "get",
url: "/api/handleError"
})
.then(res => {
console.log(res);
})
.catch(e => {
console.log(e);
}); // 2.url故意写错
axios({
method: "get",
url: "/api/handleError1"
})
.then(res => {
console.log(res);
})
.catch(e => {
console.log(e);
}); // 3. 模拟网络错误
setTimeout(() => {
axios({
method: "get",
url: "/api/handleError"
})
.then(res => {
console.log(res);
})
.catch(e => {
console.log(e);
});
}, 5000); // // 4.配置请求超时时间为2秒,模拟请求超时
axios({
method: "get",
url: "/api/handleError/timeout",
timeout: 2000
})
.then(res => {
console.log(res);
})
.catch(e => {
console.log(e.message);
});

接着在 server/server.js 添加新的接口路由:

// 响应正常情况,有50%几率响应成功,有50%几率响应失败,返回状态码500
router.get('/api/handleError', function(req, res) {
if (Math.random() > 0.5) {
res.json({
msg: `hello world`
})
} else {
res.status(500)
res.end()
}
})
// 响应请求超时情况,这里我们设置3秒后响应,而发请求那里设置了超时时间为3秒,所以会发生请求超时异常
router.get('/api/handleError/timeout', function(req, res) {
setTimeout(() => {
res.json({
msg: `hello world`
})
}, 3000)
})

最后在根目录下的index.html中加上启动该demo的入口:

<li><a href="examples/handleError">handleError</a></li>

OK,我们在命令行中执行:

# 同时开启客户端和服务端
npm run server | npm start

接着我们打开 chrome 浏览器,访问 http://localhost:8000/ 即可访问我们的 demo 了,我们点击 handleError,通过F12的控制台我们可以看到:有3条请求的响应信息都已经被打印出来了:

  • 第一条为请求成功状态,返回信息已经被打印出来
  • 第一条请求状态码为500,成功打印除了状态码信息Error: Request failed with status code 500
  • 第二条我们故意把请求的url写错,所以报了404错误,我们也成功打印出了错误信息;
  • 第三条响应超时,也打印出了超时信息Timeout of 2000 ms exceeded

接着,我们刷新浏览器,然后迅速的在5秒之内点击F12network选项,把offline勾选上,此时表示浏览器网络断开,我们就能看到模拟网络错误情况。



5. 遗留问题

OK,三种异常情况虽然都已经成功处理了,但是这仅仅是错误的文本信息,对于排错来说极不方便,所以我们最好还能够返回错误属于哪个请求、请求的配置、响应对象等其它信息。那么,下篇文章我们就来继续补充,实现异常处理的增强版。

(完)

使用Typescript重构axios(九)——异常处理:基础版的更多相关文章

  1. 使用Typescript重构axios(十)——异常处理:增强版

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  2. 使用Typescript重构axios(三)——实现基础功能:处理get请求url参数

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  3. 使用Typescript重构axios(四)——实现基础功能:处理post请求参数

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  4. 使用Typescript重构axios(五)——实现基础功能:处理请求的header

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  5. 使用Typescript重构axios(六)——实现基础功能:获取响应数据

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  6. 使用Typescript重构axios(七)——实现基础功能:处理响应header

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  7. 使用Typescript重构axios(八)——实现基础功能:处理响应data

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  8. 使用Typescript重构axios(十九)——请求取消功能:实现第二种使用方式

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  9. 使用Typescript重构axios(二十九)——添加baseURL

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

随机推荐

  1. vue项目引入bootstrap正确姿势

    vue如何引入bootstrap 最近在玩全栈,自然少不了vue的使用.使用vue-cli生成的项目想引入bootstrap,需要先安装相应的npm包,然后在代码中显示引入. 1.安装依赖包: cnp ...

  2. python编程基础之三十六

    文件处理:文件处理包括读文件,写文件 读文件: 1.打开文件 2.读取文件 3.关闭文件 写文件: 1.打开文件 2.写如文件 3.关闭文件 无论是读取文件还是写文件都时需要打开文件,和关闭文件 打开 ...

  3. 加密解密 之base系列编码

    Base16 Base16编码使用16个ASCII可打印字符(数字0-9和字母A-F)对任意字节数据进行编码.Base16先获取输入字符串每个字节的二进制值(不足8比特在高位补0),然后将其串联进来, ...

  4. conversion function——转换函数

    类型转换函数 与 explicit关键字 1.类型转换函数 在C++中,可以使用构造函数将一个指定类型的数据转换为类的对象,也可以使用类型转换函数 (type conversion function) ...

  5. cocos2d-x 3.2,Label,Action,Listener,Menu Item等简单用法

    转载自:http://blog.csdn.net/pleasecallmewhy/article/details/34931021 创建菜单(Menu Item) // 创建菜单 auto menuI ...

  6. 窥见云技术未来大势,腾讯云Techo开发者大会即将在京召开

    云.物联网.5G.人工智能……一项项技术的突破带来了天翻地覆的变化,开发者们是如何一次次地进行天马行空的创意和极限突破?2019年11月6日-7日,由腾讯云主办的首届Techo开发者大会将在北京嘉里大 ...

  7. Win10系统Cortana 小娜无法搜索

    1.在开始菜单中找“Windows PowerShell”文件夹,打开后右键单击Windows PowerShell,选择“以管理员身份运行” 2.输入命令,通过重新注册语音小娜来解决问题 Get-A ...

  8. Ubuntu8.04::扩容(LVM)磁盘

    .扩容 sudo lvextend -l +%FREE /dev/mapper/ubuntu--vg-ubuntu--lv .重新计算磁盘大小 sudo resize2fs /dev/mapper/u ...

  9. 神奇的 SQL 之团结的力量 → JOIN

    前言 开心一刻   闺蜜家暴富,买了一栋大别野,喊我去吃饭,菜挺丰盛的,筷子有些不给力,银筷子,好重,我说换个竹子的,闺蜜说,这种银筷子我家总共才五双,只有贵宾才能用~我咬着牙享受着贵宾待遇,终于,在 ...

  10. Java接口统一样式返回模板

    Java接口统一样式返回模板 背景 在进行接口开发时,一般需要一个固定的返回样式,成功和失败的时候,都按照这种格式来进行统一的返回,这样,在与其他人进行接口之间的联调时不会显得很杂乱无章.而这种固定的 ...