前面的章节我们已经可以正确的处理正确的请求,并且通过处理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. Linux Makefile 生成 *.d 依赖文件及 gcc -M -MF -MP 等相关选项说明

    1. 为什么要使用后缀名为 .d 的依赖文件? 在 Makefile 中, 我们的依赖关系可能需要包含一系列的头文件.比如main.c 源文件内容如下: #include "stdio.h& ...

  2. JS 将Table内容导出到Excel(样式设计)

    转载请注明来源:https://www.cnblogs.com/hookjc/ function saveAsExcel(tableID){ var tb = new TableToExcel(tab ...

  3. linux 设置connect 超时代码[select/epoll]

    转载请注明来源:https://www.cnblogs.com/hookjc/ linux下socket编程有常见的几个系统调用: 对于服务器来说, 有socket(), bind(),listen( ...

  4. 啥叫IP地址及子网掩码?

    啥叫IP地址及子网掩码 ??? 1.IP地址的定义及分类 1.1IP地址的定义 1.2IP地址的分类 2.子网掩码 1.1  互联网上连接的网络设备和计算机都有唯一的地址,此作为该主机在Interne ...

  5. rust 实战 - 实现一个线程工作池 ThreadPool

    如何实现一个线程池 线程池:一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间任务时创建与销毁线 ...

  6. Scala中的流程控制

    一.分支控制if-else //Scala中if-else语句中,代码块内最后一句代码就是返回值 def main(args: Array[String]): Unit = { var age:Int ...

  7. Elasticsearch按请求体基本查询

    1 分页: localhost:9200/get-together/_search {"query": {"match_all": {}},"from ...

  8. 大话PHP设计模式笔记

    针对PHP的设计模式进行总结记录. 顺带,我会在后面把我整理的一整套CSS3,PHP,MYSQL的开发的笔记打包放到百度云,有需要可以直接去百度云下载,这样以后你们开发就可以直接翻笔记不用百度搜那么麻 ...

  9. Memory Management in Rust

    程序在运行时需要请求操作系统分配内存以及释放内存,因此,程序员在编写程序时,需要显式(手动)地编写分配和释放内存的代码,或者隐式(自动,由语言保证)地进行内存管理.对于前者,C/C++ 是代表语言,程 ...

  10. Windows查看本机SSH公钥,生成公钥

    #Windows查看本机**SSH**公钥,生成公钥<br>--- ### 1.查看 ssh 公钥方法: 1. 打开你的 git bash 窗口 2. 进入 .ssh 目录:cd ~/.s ...