Wang's blog Wang's blog
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Wang Mings

跟随大神,成为大神!
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • CSS

  • Npm

  • Vue

  • HTML

  • Node

  • Yaml

  • React

  • 框架

  • 规范

  • Electron

  • JS演示

  • VuePress

  • JavaScript

  • TypeScript

  • 微信小程序

  • TypeScript-axios

    • 初识TypeScript

    • ts-axios单元测试

    • ts-axios接口扩展

    • TypeScript常用语法

    • ts-axios拦截器实现

    • ts-axios部署与发布

    • ts-axios配置化实现

    • ts-axios项目初始化

    • ts-axios取消功能实现

    • ts-axios基础功能实现

    • ts-axios异常情况处理

      • 错误处理
        • 需求分析
        • 处理网络异常错误
        • 处理超时错误
        • 处理非 200 状态码
        • demo 编写
      • 错误信息增强
    • ts-axios更多功能实现

  • 前端
  • TypeScript-axios
  • ts-axios异常情况处理
wangmings
2022-07-19
目录

错误处理

# 错误处理

# 需求分析

在上一章节,我们实现了 ts-axios 的基础功能,但目前为止我们都是处理了正常接收请求的逻辑,并没有考虑到任何错误情况的处理,这对于一个程序的健壮性而言是远不够的,因此我们这一章需要对 AJAX 各种错误情况做处理。

并且我们希望程序也能捕获到这些错误,做进一步的处理。

axios({
  method: 'get',
  url: '/error/get'
}).then((res) => {
  console.log(res)
}).catch((e) => {
  console.log(e)
})
1
2
3
4
5
6
7
8

如果在请求的过程中发生任何错误,我们都可以在 reject 回调函数中捕获到。

我们把错误分成了几类,接下来我们就来分别处理这些错误情况。

# 处理网络异常错误

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

我们在 xhr 函数中添加如下代码:

request.onerror = function handleError() {
  reject(new Error('Network Error'))
}
1
2
3

# 处理超时错误

我们可以设置某个请求的超时时间 timeout (opens new window),也就是当请求发送后超过某个时间后仍然没收到响应,则请求自动终止,并触发 timeout 事件。

请求默认的超时时间是 0,即永不超时。所以我们首先需要允许程序可以配置超时时间:

export interface AxiosRequestConfig {
  // ...
  timeout?: number
}
1
2
3
4

接着在 xhr 函数中添加如下代码:

const { /*...*/ timeout } = config

if (timeout) {
  request.timeout = timeout
}

request.ontimeout = function handleTimeout() {
  reject(new Error(`Timeout of ${timeout} ms exceeded`))
}
1
2
3
4
5
6
7
8
9

# 处理非 200 状态码

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

request.onreadystatechange = function handleLoad() {
  if (request.readyState !== 4) {
    return
  }

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

  const responseHeaders = parseHeaders(request.getAllResponseHeaders())
  const responseData =
    responseType && responseType !== 'text' ? request.response : request.responseText
  const response: AxiosResponse = {
    data: responseData,
    status: request.status,
    statusText: request.statusText,
    headers: responseHeaders,
    config,
    request
  }
  handleResponse(response)
}

function handleResponse(response: AxiosResponse) {
  if (response.status >= 200 && response.status < 300) {
    resolve(response)
  } else {
    reject(new Error(`Request failed with status code ${response.status}`))
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

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

接着我们在 handleResponse 函数中对 request.status 的值再次判断,如果是 2xx 的状态码,则认为是一个正常的请求,否则抛错。

# demo 编写

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

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Error example</title>
  </head>
  <body>
    <script src="/__build__/error.js"></script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10

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

import axios from '../../src/index'

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

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

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

axios({
  method: 'get',
  url: '/error/timeout',
  timeout: 2000
}).then((res) => {
  console.log(res)
}).catch((e) => {
  console.log(e.message)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

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

router.get('/error/get', function(req, res) {
  if (Math.random() > 0.5) {
    res.json({
      msg: `hello world`
    })
  } else {
    res.status(500)
    res.end()
  }
})

router.get('/error/timeout', function(req, res) {
  setTimeout(() => {
    res.json({
      msg: `hello world`
    })
  }, 3000)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

然后在命令行运行 npm run dev,接着打开 chrome 浏览器,访问 http://localhost:8080/ 即可访问我们的 demo 了,我们点到 Error 目录下,通过开发者工具的 network 部分我们可以看到不同的错误情况。

至此我们对各种错误都做了处理,并把它们抛给了程序应用方,让他们对错误可以做进一步的处理。但是这里我们的错误都仅仅是简单的 Error 实例,只有错误文本信息,并不包含是哪个请求、请求的配置、响应对象等其它信息。那么下一节课,我们会对错误信息做增强。

编辑 (opens new window)
处理请求body数据
错误信息增强

← 处理请求body数据 错误信息增强→

最近更新
01
theme-vdoing-blog博客静态编译问题
09-16
02
搜索引擎
07-19
03
友情链接
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2022 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式