前面的章节我们已经可以正确的处理正确的请求,并且通过处理header、body,以及加入了promise,让我们的代码更像axios了。这一章我们一起来处理ajax请求中的错误。

一、错误处理

  首先我们要知道错误有哪些类型,通常我们遇到的错误有以下几种:网络错误、超时错误和非200状态码错误。其实都不复杂我们来看下:

1、网络异常

  网络异常,会触发XMLHttpRequest的onerror事件,所以我们只需要加上就可以了:

request.onerror = function handleError() {
reject(new Error("Network Error"));
};

2、超时错误

  XMLHttpRequest对象允许配置timeout参数,默认是0,也就是永远不会超时,所以我们的代码这样处理就可以了,注意,这里的config.timeout的config,实际上就是我们传入的配置参数,只不过这里引用了一下,包括后续的完整的实现其他api的部分,有很多其实都是对原生api的一个简单的映射和转换,后面再说:

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

3、非200状态码

  如果请求报错。那么XMLHttpRequest的status属性会返回0,所以我们需要额外判断下status,中断后续的代码:

  我们在onreadystatechange回调中加入status的判断。然后我们改变一下抛出response的方式,使用一个函数来处理:

return new Promise((resolve, reject) => {
var request = new XMLHttpRequest();
config.headers = processHeaders(config.headers || {}, config.data);
config.data = transformRequest(config.data);
request.open(
config.method.toUpperCase(),
buildURL(config.url, config.params, config.paramsSerializer),
true
);
request.onreadystatechange = function handleLoad() {
if (request.readyState !== 4) {
return;
}
if (request.status === 0) {
return;
}
const responseHeaders = parseHeaders(request.getAllResponseHeaders());
const responseData =
config.responseType && config.responseType !== "text"
? request.response
: request.responseText;
const response = {
data: responseData,
status: request.status,
statusText: request.statusText,
headers: responseHeaders,
config,
request,
};
handleResponse(response);
};
// 加了这个方法来集中处理response
function handleResponse(response) {
if (response.status >= 200 && response.status < 300) {
resolve(response);
} else {
reject(new Error(`Request failed with status code ${response.status}`));
}
}

  很简单~~。错误处理完成到这里实际上就完成了,简单总结下,拦截了readystatechange事件中的status并根据对应的情况,处理response是resolve还是reject。然后根据timeout和error事件来抛出对应的错误。

  但是到这里还没真正的完成错误的处理,因为我们在错误处理的时候仅仅抛出了错误信息,没办法处理一些额外的数据,比如请求配置、响应对象等。我们下面来完成一个Error类,集中处理这些情况,让我们的代码更健壮。

二、完成AxiosError

  首先我们在core文件夹下创建一个createError文件:

export default function createError(message, config, code, request, response) {
var error = new Error(message);
return enhanceError(error, config, code, request, response);
}

  我们来看上面的代码,整个createError方法,返回了报错信息、配置、状态码、请求和响应内容。然后我们实际执行返回的是enhanceError方法。我们再来在core文件夹下创建一个enhanceError文件:

export default function enhanceError(error, config, code, request, response) {
error.config = config;
if (code) {
error.code = code;
} error.request = request;
error.response = response;
error.isAxiosError = true; error.toJSON = function toJSON() {
return {
// Standard
message: this.message,
name: this.name,
// Microsoft
description: this.description,
number: this.number,
// Mozilla
fileName: this.fileName,
lineNumber: this.lineNumber,
columnNumber: this.columnNumber,
stack: this.stack,
// Axios
config: this.config,
code: this.code,
status:
this.response && this.response.status ? this.response.status : null,
};
};
return error;
}

  上面的代码,很简单,把所有的信息绑定到error对象上,最后再返回error即可。其中需要注意的是,error.toJSON这个东西,它实际上做的就是当你在外层调用error的toJSON方法的时候,会返回这个更改后的方法。相当于改写了这个对象上的toJSON方法。

  比如我们打印下这个东西:

console.log(
createError(timeoutErrorMessage, config, "ETIMEDOUT", request).toJSON()
);

  就是enhanceError返回的那个。OK,到此我们已经写好了createError方法(其实我是从源码复制过来的,一点修改都没有)。那么我们需要修改下之前错误处理中的代码,至于具体修改的方法,就当留个作业了。大家也可以去项目中的c3分支查看。

  到此,我们处理完了错误信息,添加了新的createError方法。到目前为止,其实代码都还不是真正的axios,为什么这么说呢,到现在,我们只是实现了其中的功能,但是其实还不是真正的axios源码的组织方式,我们下一章,就来扩展整个zaking-axios,修改文件的相关性,创建Axios类等,来完成更多的功能。

一比一还原axios源码(三)—— 错误处理的更多相关文章

  1. 一比一还原axios源码(零)—— 概要

    从vue2版本开始,vue-resource就不再被vue所维护和支持,官方也推荐使用axios,所以,从我使用axios至今,差不多有四五年了,这四五年的时间只能算是熟练应用,很多内部的实现和原理不 ...

  2. 一比一还原axios源码(四)—— Axios类

    axios源码的分析,到目前为止,算上第0章已经四章了,但是实际上,还都没有进入axios真正的主线,我们来简单回顾下.最开始我们构建了get请求,写了重要的buildURL方法,然后我们处理请求体请 ...

  3. 一比一还原axios源码(一)—— 发起第一个请求

    上一篇文章,我们简单介绍了XMLHttpRequest及其他可以发起AJAX请求的API,那部分大家有兴趣可以自己去扩展学习.另外,简单介绍了怎么去读以及我会怎么写这个系列的文章,那么下面就开始真正的 ...

  4. 一比一还原axios源码(六)—— 配置化

    上一章我们完成了拦截器的代码实现,这一章我们来看看配置化是如何实现的.首先,按照惯例我们来看看axios的文档是怎么说的: 首先我们可以可以通过axios上的defaults属性来配置api. 我们可 ...

  5. 一比一还原axios源码(八)—— 其他功能

    到此,我们完成了axios的绝大部分的功能,接下来我们来补全一下其他的小功能. 一.withCredentials  这个参数可以可以表明是否是一个跨域的请求.那这个的使用场景是啥呢?就是我们在同域的 ...

  6. 一比一还原axios源码(五)—— 拦截器

    上一篇,我们扩展了Axios,构建了一个Axios类,然后通过这个Axios工厂类,创建真正的axios实例.那么今天,我们来实现下Axios的拦截器也就是interceptors.我们来简单看下Ax ...

  7. 一比一还原axios源码(二)—— 请求响应处理

    上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...

  8. axios源码解析 - 请求拦截器

    axios请求拦截器,也就是在请求发送之前执行自定义的函数. axios源码版本 - ^0.27.2 (源码是精简版) 平时在业务中会这样去写请求拦截器,代码如下: // 创建一个新的实例 var s ...

  9. Axios源码深度剖析 - 替代$.ajax,成为xhr的新霸主

    前戏 在正式开始axios讲解前,让我们先想想,如何对现有的$.ajax进行简单的封装,就可以直接使用原声Promise了? let axios = function(config){ return ...

随机推荐

  1. StarUML官网地址 http://staruml.io/

    StarUML官网地址 http://staruml.io/

  2. 抓包神器 tcpdump 使用介绍 (转)

    tcpdump 命令使用简介 简单介绍 tcpdump 是一款强大的网络抓包工具,运行在 linux 平台上.熟悉 tcpdump 的使用能够帮助你分析.调试网络数据. 要想使用很好地掌握 tcpdu ...

  3. element select失效问题 , vue刷新的两种方式

    changeSelect: function () { this.$forceUpdate(); }, 编辑一条记录,给select 赋值后就不动了, 原因是复制后组件需要刷新一下, 不然不能触发事件 ...

  4. DNS域名解析之反向解析and主从域名服务器 (今天大小便正常,未来可期)

    DNS解析之反向解析和域名主从服务器 反向解析:根据IP地址查找对应的域名 yum -y install bind 安装软件包 查看需要修改的配置文件所在路径 rpm -qc bind 查询bind软 ...

  5. MATLAB基础学习(2)

    function result=mysum(a,b)%创建函数以及外部接口 s=0; for i=a:b s=s+i; end result=s; disp(s); end Matlab中ones() ...

  6. postman python疑难

    例子1:postman请求时会将默认的headers的content-type替换成Content-Type,而直接使用python的request则不行,服务器端就会接收到错误的Content-Ty ...

  7. pycharm工具使用

    转自: https://blog.csdn.net/u014044812/article/details/78727496   因公司的需求,需要做一个爬取最近上映的电影.列车号.航班号.机场.车站等 ...

  8. PHP+mysql真题

    PHP+mysql真题 来自<PHP程序员面试笔试宝典>,涵盖了近三年了各大型企业常考的PHP面试题,针对面试题提取出来各种面试知识也涵盖在了本书. [真题215] 按要求写出SQL实现. ...

  9. CentOS7搭建yum源仓库(阿里源)

    文章目录 注意:环境要求 1.配置服务器端yum 1.1.安装yum源工具 1.2.配置nginx 1.2.1.配置nginx页面目录 1.3.替换yum源文件 1.4.建立yum源仓库 2.配置客户 ...

  10. CentOS7下Jumpserver V3.0 部署

    环境准备 # 准备一台 2核4G (最低)且可以访问互联网的 64 位 Centos 7 主机 [root@localhost ~]# hostnamectl --static set-hostnam ...