Meta tags:
description= axios实例应用及源码剖析 - xhr篇 (走心教程). Contribute to ronffy/axios-tutorial development by creating an account on GitHub.;
Headings (most frequently used words):
源码分析, 如何使用, uh, oh, navigation, saved, searches, axios, files, footer, search, code, repositories, users, issues, pull, requests, provide, feedback, ronffy, tutorial, axios源码深度剖析, xhr篇, menu, use, to, filter, your, results, more, quickly, folders, and, latest, commit, history, repository, 分析axios, 目录, axios的应用和源码解析, about, releases, packages, contributors, languages, 备注, axios项目目录结构, 名词解释, axios内部的运作流程图, 工具方法简单介绍, axios为何会有多种使用方式, 用户配置的config是怎么起作用的, prototype, request, 如何拦截请求响应并修改请求参数修改响应数据, dispatchrequest都做了哪些事, axios是如何用promise搭起基于xhr的异步桥梁的, 数据转换器, 转换请求与响应数据, 自动转换json数据, header设置, 如何取消已经发送的请求, 跨域携带cookie, 超时配置及处理, 改写验证成功或失败的规则validatestatus, 总结, topics, resources, license, stars, watchers, forks, 思考, 转换器和拦截器的关系, 发现的问题,
Text of the page (most frequently used words):
axios (129), config (79), request (69), data (53), function (50), return (44), #promise (40), defaults (40), response (39), headers (39), var (37), lib (34), prototype (34), this (30), utils (30), url (23), chain (22), method (21), dispatchrequest (21), get (19), xhr (18), canceltoken (18), reject (17), foreach (17), interceptors (17), status (16), resolve (16), new (16), cancel (16), source (16), then (16), error (15), merge (14), interceptor (14), interceptormanager (14), core (13), adapters (13), reason (13), github (12), code (12), validatestatus (12), transformresponse (12), 源码分析 (11), from (11), transformrequest (11), security (10), import (10), 如何使用 (10), rejected (10), use (10), context (10), json (9), shift (9), instance (9), while (8), post (8), fulfilled (8), all (8), reload (7), settle (7), message (7), transformdata (7), adapter (7), xhradapter (7), handlers (7), bind (7), option (7), view (7), and (7), you (6), null (6), timeout (6), const (6), token (6), 处理data (6), extend (6), your (6), enterprise (6), navigation (5), license (5), xmlhttprequest (5), 省略代码 (5), issues (5), catch (5), application (5), push (5), length (5), undefined (5), support (5), instanceconfig (5), createinstance (5), index (5), search (5), community (4), there (4), was (4), loading (4), please (4), page (4), readme (4), http (4), with (4), loadevent (4), withcredentials (4), 用户配置的config是怎么起作用的 (4), resolvepromise (4), common (4), charset (4), utf (4), 数据转换器 (4), axios是如何用promise搭起基于xhr的异步桥梁的 (4), delete (4), eject (4), eat (4), 如何拦截请求响应并修改请求参数修改响应数据 (4), value (4), create (4), tree (4), actions (4), quality (4), stars (3), resources (3), topics (3), xhr篇 (3), onreadystatechange (3), true (3), let (3), abort (3), executor (3), content (3), type (3), setcontenttypeifunset (3), axios为何会有多种使用方式 (3), put (3), baseurl (3), 名词解释 (3), whr (3), require (3), 工具方法简单介绍 (3), package (3), more (3), files (3), commit (3), name (3), open (3), ronffy (3), tutorial (3), insights (3), pull (3), requests (3), signed (3), settings (3), another (3), tab (3), window (3), refresh (3), session (3), sign (3), saved (3), documentation (3), feedback (3), grade (3), features (3), copilot (3), platform (3), solutions (3), explore (3), can (2), manage (2), footer (2), releases (2), repository (2), forks (2), 248 (2), mit (2), axios实例应用及源码剖析 (2), 走心教程 (2), createerror (2), else (2), 204 (2), 1223 (2), readystate (2), handleload (2), 300 (2), 200 (2), 改写验证成功或失败的规则validatestatus (2), handletimeout (2), ontimeout (2), 3000 (2), 超时配置及处理 (2), 由此得出 (2), 跨域携带cookie (2), js文件中 (2), b请求成功了 (2), burl (2), aurl (2), 取消日志 (2), 如何取消已经发送的请求 (2), www (2), form (2), urlencoded (2), header设置 (2), ignore (2), parse (2), try (2), string (2), typeof (2), stringify (2), isobject (2), 自动转换json数据 (2), onadapterrejection (2), onadapterresolution (2), fns (2), 转换请求与响应数据 (2), 方法会调用 (2), 将config对象当作参数传给primise (2), resolve方法 (2), 最终都是调用的 (2), patch (2), head (2), dispatchrequest都做了哪些事 (2), 所以通过promise实现链式调用时 (2), 所以得出结论 (2), 对于响应拦截器 (2), 又通过shift方法从chain数组里取出的 (2), 对于请求拦截器 (2), pushresponseinterceptors (2), unshift (2), unshiftrequestinterceptors (2), 关于拦截器 (2), apple (2), durian (2), sleep (2), 是否可以直接 (2), myrequestinterceptor (2), 拦截器 (2), dispatchrequest方法 (2), 请求拦截器 (2), 响应拦截器 (2), axios实例属性 (2), 请求的参数 (2), configname (2), request方法 (2), http请求适配器 (2), options (2), 创建一个axios实例 (2), 就有了 (2), 方式调用 (2), defaultconfig (2), 等方法 (2), extendobj (2), target (2), log (2), console (2), 111 (2), bbb (2), obj2 (2), obj1 (2), 后面用到了再过来查看 (2), axios内部的运作流程图 (2), 有的地方叫它 (2), 顾名思义 (2), axios项目目录结构 (2), webpack (2), png (2), entry (2), ejs (2), jpg (2), gitignore (2), eslintrc (2), eslintignore (2), commits (2), last (2), menu (2), projects (2), appearance (2), see (2), available (2), searches (2), repositories (2), business (2), advanced (2), developer (2), customer (2), services (2), devops (2), app (2), perform, that, action, time, not, share, personal, information, cookies, contact, docs, privacy, terms, 2026, inc, html, javascript, languages, contributors, packages, published, report, watching, watchers, activity, ajax, about, 这个能够在github斩获42k, 截止2018, 的star, 实力绝不是概的, 值得好好交交心, axios这个项目里, 有很多对js使用很巧妙的地方, 比如对promise的串联操作, 当然你也可以说这块是借鉴很多异步中间件的处理方式, 让我们可以很方便对请求前后的各种处理方法的流程进行控制, 很多实用的小优化, 比如请求前后的数据处理, 省了程序员一遍一遍去写json, xxx了, 同时支持了浏览器和node两种环境, 对使用node的项目来说无疑是极好的, failed, validatestatus验证通过, 就会触发resolve方法, 如果我们往上捣一捣就会发现, config对象的validatestatus就是我们自定义的validatestatus方法或默认的validatestatus方法, sends, instead, https, com, 201, xdomain, 改变时, 就会触发, axios是何时开始验证http状态码的, 在默认配置中, 定义了默认的http状态码验证规则, 所以自定义, 其实是对此处方法的重写, 自定义http状态码的成功, 失败范围, 超时处理, indexof, axios库外如何添加超时后的处理, econnaborted, exceeded, 通过createerror方法, 将错误信息合为一个字符串, 我们在, 一节已经介绍了config在axios项目里的传递过程, 我们通过, 做的配置, 里是可以取到的, 然后通过以下代码配置到xhr对象项, oncanceled方法里, reject里应该将config信息也传出来, oncanceled方法的参数不应该叫message么, 为什么叫cancel, 发现的问题, 相对来说, 我更推崇第1种写法, 因为第2种写法太隐蔽了, 不如第一种直观好理解, 第2种写法, 第1种写法, 上面第二种写法可以看作是对第一种写法的完善, 因为很多是时候我们取消请求的方法是用在本次请求方法外, 发送a, b两个请求, 当b请求成功后, 取消a请求, 参数拿到对, 方法的控制权, 这样当执行, 方法时就可以改变实例的, 属性的状态为, 从而执行, 方法达到取消请求的目的, 取消功能的核心是通过canceltoken内的, 得到实例属性, 此时该, 的状态为, 通过这个属性, 文件中继续给这个, 实例添加, 文件的159行, pending, oncanceled, 159行, promiseexecutor, 11行, 第二种取消方法, 取消条件, 第一种取消方法, 44行, whr1, authorization, 设置某次请求的header, 设置某种请求的header, xhr标识, requested, 设置通用header, axios项目的运作流程已经介绍完毕, 是不是已经打通了任督二脉了呢, 接下来我们一起看下axios还带给了我们哪些好用的技能点吧, 得到响应后, 将请求到的数据转换为json对象, 请求时, 将data数据转换为json, 字符串, 在默认情况下, axios将会自动的将传入的data对象序列化为json字符串, 将响应数据中的json字符串转换为javascript对象, axios官方是将, 自动转换为json数据, 作为一个独立的亮点来介绍的, 那么数据转换器是如何完成这个功能的呢, 其实非常简单, 我们一起看下吧, 拦截器同样可以实现转换请求和响应数据的需求, 但根据作者的设计和综合代码可以看出, 在请求时, 拦截器主要负责修改config配置项, 数据转换器主要负责转换请求体, 比如转换对象为字符串, 在请求响应后, 拦截器可以拿到, 数据转换器主要负责处理响应体, 比如转换字符串为对象, 转换器和拦截器的关系, iscancel, 响应转换器的使用地方是在http请求完成后, 根据http请求适配器的返回值做数据转换处理, transform, 方法的代码, 主要遍历转换器数组, 分别执行每一个转换器, 根据data和headers参数, 返回新的data, 请求转换器的使用地方是http请求前, 使用请求转换器对请求数据做处理, 然后传给http请求适配器使用, 那么在axios项目里, 是在什么地方使用了转换器呢, tostring, isurlsearchparams, buffer, isarraybufferview, normalizeheadername, 默认的, 配置项里已经自定义了一个请求转换器和一个响应转换器, 看下源码, 去掉这行代码就等于重写响应转换器了, 去掉这行代码就等于重写请求转换器了, 往已经存在的转换器里增加转换方法, 修改某次axios请求的转换器, 重写响应转换器, 往现有的响应转换器里增加转换方法, 重写请求转换器, 往现有的请求转换器里增加转换方法, 修改全局的转换器, 回过头来, 我们在介绍, 一节时说到的数据转换, 而axios官方也将数据转换专门作为一个亮点来介绍的, 那么数据转换到底能在使用axios发挥什么功效呢, 那么至此, 用户调用, 方法时, 就可以直接调用promise的, 进行业务处理了, 方法内, 首先得到, 方法返回的promise对象, 然后通过, 返回的promise对象的成功或失败结果再次加工, 成功的话, 则将处理后的, 失败的话, 则返回一个状态为, 的promise对象, 验证服务端的返回结果是否通过验证, handleerror, onerror, 往下走有settle的源码, 内的xhr发送请求成功后会执行这个promise对象的, 并将请求的数据传出去, 反之则执行, 并将错误信息作为参数传出去, dispatchxhrrequest, 方法返回的是还一个promise对象, 我们知道, 用户无论以什么方式调用axios, 这个方法最终返回的是一个promise对象, 先来一个图简单的了解下axios项目里, http请求完成后到达用户的顺序流, 此处可以拿到请求失败或取消或其他处理失败的错误对象, 此处可以拿到向服务端请求回的数据, axios是如何通过promise进行异步处理的, 看到这里, 我们是时候梳理一下, 不过大部分时候, axios提供的默认适配器是能够满足我们的, http请求适配器会优先使用config上自定义的适配器, 没有配置时才会使用默认的xhr或http适配器, cleanheaderconfig, 删除header属性里无用的属性, 对header进行合并处理, 对请求data进行转换, ensure, exist, combineurls, isabsoluteurl, throwifcancellationrequested, exports, module, dispatchrequest主要做了3件事, 拿到config对象, 对config进行传给http请求适配器前的最后处理, http请求适配器根据config配置, 发起请求, http请求适配器请求完成后, 如果成功则根据header, 和config, 关于transformresponse, 下面的, 会进行讲解, 拿到数据转换后的response, 并return, 你应该已经清楚了拦截器是怎么回事, 以及拦截器是如何在, 方法里发挥作用的了, 那么处于, 中游位置, 是如何发送http请求的呢, 响应拦截器一定会等待, 执行完后再开始执行, 也就是, 方法一定会等待所有的请求拦截器执行完后再开始执行, 而拦截器的执行顺序还是会按照我们上面说的顺序执行, 因为axios是通过promise实现的链式调用, 所以我们可以在拦截器里进行异步操作, 所以dispatchrequest抛出的错误才会被响应拦截器接收到, 任何一个拦截器的抛出的错误, 都会被下一个拦截器的rejected函数收到, 每个响应拦截器的fulfilled函数都会接收到一个response对象, 而响应拦截器又规定用户写的fulfilled函数必须返回一个response对象, 第一个响应拦截器的fulfilled函数会接受到dispatchrequest, 也就是我们的请求方法, 请求到的数据, 也就是response对象, 每个请求拦截器的fulfilled函数都会接收到一个config对象, 而请求拦截器又规定用户写的fulfilled函数必须返回一个config对象, 第一个请求拦截器的fulfilled函数会接收到promise对象初始化时传入的config对象, 添加的拦截器先执行, 从拦截器数组按序读到后是通过push方法往chain数组里添加的, 先添加的拦截器会后执行, 从拦截器数组按序读到后是通过unshift方法往chain数组数里添加的, 通过interceptormanager, use往拦截器数组里添加拦截器时使用的数组的push方法, 正好每次添加的就是我们通过interceptormanager, use方法添加的成功和失败回调, 按照我们使用interceptormanager, use添加拦截器的规则, 每次执行while循环, 从chain数组里按序取出两项, 并分别作为promise, then方法的第一个和第二个参数, 数组的, 方法用于把数组的第一个元素从其中删除, 并返回第一个元素的值, 只要chain数组长度不为0, 就一直执行while循环, responsefulfilledfn, responserejectedfn, requestfulfilledfn, requestrejectedfn, 添加了拦截器后的chain数组大概会是这样的, 是可能为undefined, 初始化一个promise对象, 状态为resolved, 接收到的参数为config对象, 先看下代码, 那么当我们通过, 添加拦截器后, axios内部又是怎么让这些拦截器能够在请求前, 请求后拿到我们想要的数据的呢, foreachhandler, 遍历this, 并将this, handlers里的每一项作为参数传给fn执行, 用来注销指定的拦截器, 往拦截器里添加拦截方法, 存放拦截器方法, 数组内每一项都是有两个属性的对象, 两个属性分别对应成功和失败后执行的函数, 构造函数就是用来实现拦截器的, 这个构造函数原型上有3个方法, 关于源码, 其实是比较简单的, 都是用来操作该构造函数的handlers实例属性的, 我们先来看看, 构造函数, 这两个属性都是一个, 而这个, 构造函数就是用来管理拦截器的, 每个axios实例都有一个, 实例属性, 对象上有两个属性, 一节已经做过简单说明, 等待3s, 等待5s, 打印结果, 5000, people, 如何实现promise的链式调用, 移除某次拦截器, 对响应错误做点什么, 有且必须有一个response对象被返回, 对响应数据做点什么, 添加响应拦截器, 对请求错误做些什么, 有且必须有一个config对象被返回, 在发送http请求之前做些什么, 添加请求拦截器, 你一定对拦截器充满了好奇, 这个拦截器到底是个什么家伙, 下一节就让我们一探究竟吧, 查看源码, 数组是用来盛放拦截器方法和, 方法的, 通过promise从, 数组里按序取出回调函数逐一执行, 最后将处理后的新的promise在, 方法里返回出去, 并将response或error传送出去, 这就是, 的使命了, 这里面的代码比较复杂, 一些方法需要追根溯源才能搞清楚, 所以只需对chain数组有个简单的了解就好, 涉及到的, 后面都会详细介绍, 走完了它传奇的一生, 下一节就要说到重头戏了, 下面会作为一个专门的小节来介绍, config会按序通过, 我们已经得到了将多处, 那么这个对象在项目中又是怎样传递的呢, 留给大家思考一个问题, 什么时候配置是相同的, 什么时候是不同的, 多处配置的优先级由低到高是, 默认配置对象, 可以发现此处将默认配置对象, 进行了合并, 方法里的一行代码, 第35行, newaxiosinstance, 第3种, 新建一个axios实例, 传入配置项, 此处设置的是通用配置, 第2种, 发起请求时最终会调用axios, 然后传入配置项, 主要用来设置, 第1种, 直接修改axios实例上defaults属性, 主要用来设置通用配置, 首先我们看看, 用户能以什么方式定义配置项, 可以发现, 所有的功能都是通过这个对象进行配置和传递的, 项目内部的沟通桥梁, 也是用户跟, 进行沟通的桥梁, 请求地址, 请求方法, 请求头header, 请求数据, 请求或响应数据的转换, 请求进度, http状态码验证规则, 取消请求等, 这里说的, 指的是贯穿整个项目的配置项对象, 通过这个对象, 可以设置, 在开始说, 我们先来捋一捋在axios项目中, 说完axios为什么会有这么多种使用方式, 可能你心中会有一个疑问, 使用axios时, 方法还是, 那么这个方法是怎么根据我们的config配置发请求的呢, 31行, 一般情况, 项目使用默认导出的axios实例就可以满足需求了, 如果不满足需求需要创建新的axios实例, axios包也预留了接口, 看下面的代码, 通过以上代码, 我们就可以以多种方式发起http请求了, foreachmethodwithdata, foreachmethodnodata, 为支持的请求方法提供别名, 是axios包的核心, 实例就是一个axios应用, 其他方法都是对, 内容的扩展, 构造函数的核心方法是, 各种axios的调用方式最终都是通过, 方法发请求的, 那么再来看看, 的源码是怎样的, 以上代码看上去很绕, 最终是希望拿到一个function, 这个function指向, 这个function还会有, 上的每个方法作为静态方法, 且这些方法的上下文都是指向同一个对象, 接收默认配置项作为参数, 后面会介绍配置项, 最终会被作为对象导出, 这两个属性后面我们会介绍, 因为extend内部使用的foreach方法对对象做for, 遍历时, 只遍历对象本身的属性, 而不会遍历原型链上的属性, 把context对象上的自身属性和方法扩展到instance上, 并指定上下文为context, 这样执行axios原型链上的方法时, this会指向context, put等方法, 把axios, prototype上的方法扩展到instance对象上, 内对第一个参数的数据类型判断, 使我们能够以, 这样instance就指向了request方法, 且上下文指向context, 所以可以直接以, 以下代码也可以这样实现, 作为axios项目的入口文件, 我们先来看下, 的源码, 能够实现axios的多种使用方式的核心是, 第5种使用方式, 第4种使用方式, 第3种使用方式, 第2种使用方式, 第1种使用方式, 首先将axios包引进来, extendobj对象是, 将一个对象的方法和属性扩展到另外一个对象上, 并指定上下文, mergedobj对象是, mergedobj, 深度合并多个对象为一个对象, object, key, array, 遍历数组或对象, 实现效果同, 给某个函数指定上下文, 也就是this指向, 有一些方法在项目中多处使用, 简单介绍下这些方法, 本节可先跳过, config在axios项目里的是非常重要的一条链, 是用户跟axios项目内部, 的主要桥梁, 在axios项目中的, 读取config时, 这儿是默认配置项, 的参数, http请求适配器方法的参数, 此处我们说的config, 在项目内不是真的都叫config这个变量名, 这个名字是我根据它的用途起的一个名字, 方便大家理解, config配置项, 其实就是一个对象, 本次分享主要围绕xhr, axios也留给了用户通过config自行配置适配器的接口的, 一般情况下, 这两种适配器就能够满足从浏览器端向服务端发请求或者从node的http客户端向服务端发请求的需求, 在axios项目里, http请求适配器主要指两种, xhr的核心是浏览器端的xmlhttprequest对象, http核心是node的http, 其实就是一个方法, 数据转换器分为请求转换器和响应转换器, 请求转换器, 是指在请求前对数据进行转换, 响应转换器, 主要对请求响应后的响应体做数据转换, 其实就是对数据进行转换, 比如将对象转换为json字符串, 这里先简单说明, 后面会做详细的介绍, 拦截器分为请求拦截器和响应拦截器, 是指可以拦截住每次或指定http请求, 并可修改配置项, 可以在每次http请求后拦截住每次或指定http请求, 并可修改返回结果项, 如果你熟悉中间件, 那么就很好理解了, 因为它起到的就是基于promise的中间件的作用, 因为我们需要要看的代码都是, 目录下的文件, 所以以下所有涉及到文件路径的地方, 我们都会在, 下进行查找, dist, 项目输出目录, 项目源码目录, 定义取消功能, 一些核心功能, axios的核心主类, 用来调用http请求适配器方法发送请求, 拦截器构造函数, 根据http响应状态, 改变promise的状态, helpers, 一些辅助方法, 定义请求的适配器, 实现http适配器, 实现xhr适配器, 对外暴露接口, 默认配置, 公用工具, 项目信息, 配置typescript的声明文件, 入口文件, axios的应用和源码解析, axios最核心的技术点是, 一节可先跳过, 每一小节都会从两个方面介绍, 分析axios, 是一个基于, 的http请求库, 可以用在浏览器和node, js中, 目前在github上有, 42k, 的star数, axios源码深度剖析, items, history, latest, date, folders, file, tags, branches, master, additional, star, fork, must, change, notification, notifications, public, dismiss, alert, switched, accounts, out, resetting, focus, qualifiers, our, query, filter, results, quickly, submit, include, email, address, contacted, read, every, piece, take, input, very, seriously, provide, syntax, tips, clear, users, jump, pricing, premium, for, add, ons, powered, collections, trending, archive, program, accelerator, maintainer, lab, programs, fund, developers, sponsors, partners, trust, center, forum, skills, ebooks, reports, events, webinars, stories, software, development, topic, industries, government, manufacturing, financial, healthcare, industry, cases, devsecops, modernization, case, nonprofits, startups, small, medium, teams, enterprises, company, size, marketplace, changelog, blog, why, stop, leaks, before, they, start, secret, protection, secure, build, find, fix, vulnerabilities, enforce, changes, review, plan, track, work, instant, dev, environments, codespaces, automate, any, workflow, workflows, integrate, external, tools, mcp, registry, direct, agents, issue, write, better, creation, toggle, skip,
Text of the page (random words):
faults lib defaults js method get axios实例属性 this defaults request 请求的参数 config 留给大家思考一个问题 defaults 和 this defaults 什么时候配置是相同的 什么时候是不同的 至此 我们已经得到了将多处 merge 后的 config 对象 那么这个对象在项目中又是怎样传递的呢 axios prototype request function request config config utils merge defaults method get this defaults config var chain dispatchrequest undefined 将config对象当作参数传给primise resolve方法 var promise promise resolve config 省略代码 while chain length config会按序通过 请求拦截器 dispatchrequest方法 响应拦截器 关于拦截器 和 dispatchrequest方法 下面会作为一个专门的小节来介绍 promise promise then chain shift chain shift return promise 至此 config 走完了它传奇的一生 _ 下一节就要说到重头戏了 axios prototype request axios prototype request 这里面的代码比较复杂 一些方法需要追根溯源才能搞清楚 所以只需对chain数组有个简单的了解就好 涉及到的 拦截器 dispatchrequest 后面都会详细介绍 chain 数组是用来盛放拦截器方法和 dispatchrequest 方法的 通过promise从 chain 数组里按序取出回调函数逐一执行 最后将处理后的新的promise在 axios prototype request 方法里返回出去 并将response或error传送出去 这就是 axios prototype request 的使命了 查看源码 lib core axios js axios prototype request function request config var chain dispatchrequest undefined var promise promise resolve config this interceptors request foreach function unshiftrequestinterceptors interceptor chain unshift interceptor fulfilled interceptor rejected this interceptors response foreach function pushresponseinterceptors interceptor chain push interceptor fulfilled interceptor rejected while chain length promise promise then chain shift chain shift return promise 此时 你一定对拦截器充满了好奇 这个拦截器到底是个什么家伙 下一节就让我们一探究竟吧 如何拦截请求响应并修改请求参数修改响应数据 如何使用 添加请求拦截器 const myrequestinterceptor axios interceptors request use config 在发送http请求之前做些什么 return config 有且必须有一个config对象被返回 error 对请求错误做些什么 return promise reject error 添加响应拦截器 axios interceptors response use response 对响应数据做点什么 return response 有且必须有一个response对象被返回 error 对响应错误做点什么 return promise reject error 移除某次拦截器 axios interceptors request eject myrequestinterceptor 思考 是否可以直接 return error axios interceptors request use config config error 是否可以直接 return error return promise reject error 如何实现promise的链式调用 new people whr sleep 3000 eat apple sleep 5000 eat durian 打印结果 等待3s whr eat apple 等待5s whr eat durian 源码分析 关于拦截器 名词解释 一节已经做过简单说明 每个axios实例都有一个 interceptors 实例属性 interceptors 对象上有两个属性 request response function axios instanceconfig this interceptors request new interceptormanager response new interceptormanager 这两个属性都是一个 interceptormanager 实例 而这个 interceptormanager 构造函数就是用来管理拦截器的 我们先来看看 interceptormanager 构造函数 interceptormanager 构造函数就是用来实现拦截器的 这个构造函数原型上有3个方法 use eject foreach 关于源码 其实是比较简单的 都是用来操作该构造函数的handlers实例属性的 lib core interceptormanager js function interceptormanager this handlers 存放拦截器方法 数组内每一项都是有两个属性的对象 两个属性分别对应成功和失败后执行的函数 往拦截器里添加拦截方法 interceptormanager prototype use function use fulfilled rejected this handlers push fulfilled fulfilled rejected rejected return this handlers length 1 用来注销指定的拦截器 interceptormanager prototype eject function eject id if this handlers id this handlers id null 遍历this handlers 并将this handlers里的每一项作为参数传给fn执行 interceptormanager prototype foreach function foreach fn utils foreach this handlers function foreachhandler h if h null fn h 那么当我们通过 axios interceptors request use 添加拦截器后 axios内部又是怎么让这些拦截器能够在请求前 请求后拿到我们想要的数据的呢 先看下代码 lib core axios js axios prototype request function request config var chain dispatchrequest undefined 初始化一个promise对象 状态为resolved 接收到的参数为config对象 var promise promise resolve config 注意 interceptor fulfilled 或 interceptor rejected 是可能为undefined this interceptors request foreach function unshiftrequestinterceptors interceptor chain unshift interceptor fulfilled interceptor rejected this interceptors response foreach function pushresponseinterceptors interceptor chain push interceptor fulfilled interceptor rejected 添加了拦截器后的chain数组大概会是这样的 requestfulfilledfn requestrejectedfn dispatchrequest undefined responsefulfilledfn responserejectedfn 只要chain数组长度不为0 就一直执行while循环 while chain length 数组的 shift 方法用于把数组的第一个元素从其中删除 并返回第一个元素的值 每次执行while循环 从chain数组里按序取出两项 并分别作为promise then方法的第一个和第二个参数 按照我们使用interceptormanager prototype use添加拦截器的规则 正好每次添加的就是我们通过interceptormanager prototype use方法添加的成功和失败回调 通过interceptormanager prototype use往拦截器数组里添加拦截器时使用的数组的push方法 对于请求拦截器 从拦截器数组按序读到后是通过unshift方法往chain数组数里添加的 又通过shift方法从chain数组里取出的 所以得出结论 对于请求拦截器 先添加的拦截器会后执行 对于响应拦截器 从拦截器数组按序读到后是通过push方法往chain数组里添加的 又通过shift方法从chain数组里取出的 所以得出结论 对于响应拦截器 添加的拦截器先执行 第一个请求拦截器的fulfilled函数会接收到promise对象初始化时传入的config对象 而请求拦截器又规定用户写的fulfilled函数必须返回一个config对象 所以通过promise实现链式调用时 每个请求拦截器的fulfilled函数都会接收到一个config对象 第一个响应拦截器的fulfilled函数会接受到dispatchrequest 也就是我们的请求方法 请求到的数据 也就是response对象 而响应拦截器又规定用户写的fulfilled函数必须返回一个response对象 所以通过promise实现链式调用时 每个响应拦截器的fulfilled函数都会接收到一个response对象 任何一个拦截器的抛出的错误 都会被下一个拦截器的rejected函数收到 所以dispatchrequest抛出的错误才会被响应拦截器接收到 因为axios是通过promise实现的链式调用 所以我们可以在拦截器里进行异步操作 而拦截器的执行顺序还是会按照我们上面说的顺序执行 也就是 dispatchrequest 方法一定会等待所有的请求拦截器执行完后再开始执行 响应拦截器一定会等待 dispatchrequest 执行完后再开始执行 promise promise then chain shift chain shift return promise 现在 你应该已经清楚了拦截器是怎么回事 以及拦截器是如何在 axios prototype request 方法里发挥作用的了 那么处于 中游位置 的 dispatchrequest 是如何发送http请求的呢 dispatchrequest都做了哪些事 dispatchrequest主要做了3件事 1 拿到config对象 对config进行传给http请求适配器前的最后处理 2 http请求适配器根据config配置 发起请求 3 http请求适配器请求完成后 如果成功则根据header data 和config transformresponse 关于transformresponse 下面的 数据转换器 会进行讲解 拿到数据转换后的response 并return lib core dispatchrequest js module exports function dispatchrequest config throwifcancellationrequested config support baseurl config if config baseurl isabsoluteurl config url config url combineurls config baseurl config url ensure headers exist config headers config headers 对请求data进行转换 config data transformdata config data config headers config transformrequest 对header进行合并处理 config headers utils merge config headers common config headers config method config headers 删除header属性里无用的属性 utils foreach delete get head post put patch common function cleanheaderconfig method delete config headers method http请求适配器会优先使用config上自定义的适配器 没有配置时才会使用默认的xhr或http适配器 不过大部分时候 axios提供的默认适配器是能够满足我们的 var adapter config adapter defaults adapter return adapter config then 好了 看到这里 我们是时候梳理一下 axios是如何用promise搭起基于xhr的异步桥梁的 axios是如何用promise搭起基于xhr的异步桥梁的 axios是如何通过promise进行异步处理的 如何使用 import axios from axios axios get then data 此处可以拿到向服务端请求回的数据 catch error 此处可以拿到请求失败或取消或其他处理失败的错误对象 源码分析 先来一个图简单的了解下axios项目里 http请求完成后到达用户的顺序流 通过 axios为何会有多种使用方式 我们知道 用户无论以什么方式调用axios 最终都是调用的 axios prototype request 方法 这个方法最终返回的是一个promise对象 axios prototype request function request config var chain dispatchrequest undefined 将config对象当作参数传给primise resolve方法 var promise promise resolve config while chain length promise promise then chain shift chain shift return promise axios prototype request 方法会调用 dispatchrequest 方法 而 dispatchrequest 方法会调用 xhradapter 方法 xhradapter 方法返回的是还一个promise对象 lib adapters xhr js function xhradapter config return new promise function dispatchxhrrequest resolve reject 省略代码 xhradapter 内的xhr发送请求成功后会执行这个promise对象的 resolve 方法 并将请求的数据传出去 反之则执行 reject 方法 并将错误信息作为参数传出去 lib adapters xhr js var request new xmlhttprequest var loadevent onreadystatechange request loadevent function handleload 往下走有settle的源码 settle resolve reject response request onerror function handleerror reject request null request ontimeout function handletimeout reject request null 验证服务端的返回结果是否通过验证 lib core settle js function settle resolve reject response var validatestatus response config validatestatus if response status validatestatus validatestatus response status resolve response else reject 回到 dispatchrequest 方法内 首先得到 xhradapter 方法返回的promise对象 然后通过 then 方法 对 xhradapter 返回的promise对象的成功或失败结果再次加工 成功的话 则将处理后的 response 返回 失败的话 则返回一个状态为 rejected 的promise对象 return adapter config then function onadapterresolution response return response function onadapterrejection reason return promise reject reason 那么至此 用户调用 axios 方法时 就可以直接调用promise的 then 或 catch 进行业务处理了 回过头来 我们在介绍 dispatchrequest 一节时说到的数据转换 而axios官方也将数据转换专门作为一个亮点来介绍的 那么数据转换到底能在使用axios发挥什么功效呢 数据转换器 转换请求与响应数据 如何使用 修改全局的转换器 import axios from axios 往现有的请求转换器里增加转换方法 axios defaults transformrequest push data headers 处理data return data 重写请求转换器 axios defaults transformrequest data headers 处理data return data 往现有的响应转换器里增加转换方法 axios defaults transformresponse push data headers 处理data return data 重写响应转换器 axios defaults transformresponse data headers 处理data return data 修改某次axios请求的转换器 import axios from axios 往已经存在的转换器里增加转换方法 axios get url transformrequest axios defaults transformrequest 去掉这行代码就等于重写请求转换器了 data headers 处理data return data transformresponse axios defaults transformresponse 去掉这行代码就等于重写响应转换器了 data headers 处理data return data 源码分析 默认的 defaults 配置项里已经自定义了一个请求转换器和一个响应转换器 看下源码 lib defaults js var defaults transformrequest function transformrequest data headers normalizeheadername headers content type if utils isarraybufferview data return data buffer if utils isurlsearchparams data setcontenttypeifunset headers application x www form urlencoded charset utf 8 return data tostring if utils isobject data setcontenttypeifunset headers application json charset utf 8 return json stringify data return data transformresponse function transformresponse data if typeof data string try data json parse data catch e ignore return data 那么在axios项目里 是在什么地方使用了转换器呢 请求转换器的使用地方是http请求前 使用请求转换器对请求数据做处理 然后传给http请求适配器使用 lib core dispatchrequest js function dispatchrequest config config data transformdata config data config headers config transformrequest return adapter config then 看下 transformdata 方法的代码 主要遍历转换器数组 分别执行每一个转换器 根据data和headers参数 返回新的data lib core transformdata js function transformdata data headers fns utils foreach fns function transform fn data fn data headers return data 响应转换器的使用地方是在http请求完成后 根据http请求适配器的返回值做数据转换处理 lib core dispatchrequest js return adapter config then function onadapterresolution response response data transformdata response data response headers config transformresponse return response function onadapterrejection reason if iscancel reason if reason reason response reason response data transformdata reason response data reason response headers config transformresponse return promise reject reason 转换器和拦截器的关系 拦截器同样可以实现转换请求和响应数据的需求 但根据作者的设计和综合代码可以看出 在请求时 拦截器主要负责修改config配置项 数据转换器主要负责转换请求体 比如转换对象为字符串 在请求响应后 拦截器可以拿到 response 数据转换器主要负责处理响应体 比如转换字符串为对象 axios官方是将 自动转换为json数据 作为一个独立的亮点来介绍的 那么数据转换器是如何完成这个功能的呢 其实非常简单 我们一起看下吧 自动转换json数据 在默认情况下 axios将会自动的将传入的data对象序列化为json字符串 将响应数据中的json字符串转换为javascript对象 源码分析 请求时 将data数据转换为json 字符串 lib defaults js transformrequest function transformrequest data headers if utils isobject data setcontenttypeifunset headers application json charset utf 8 return json stringify data return data 得到响应后 将请求到的数据转换为json对象 lib defaults js transformresponse function transformresponse data if typeof data string try data json parse data catch e ignore return data 至此 axios项目的运作流程已经介绍完毕 是不是已经打通了任督二脉了呢 接下来我们一起看下axios还带给了我们哪些好用的技能点吧 header设置 如何使用 import axios from axios 设置通用header axios defaults headers common x requested with xmlhttprequest xhr标识 设置某种请求的header axios defaults headers post content type application x www form urlencoded charset utf 8 设置某次请求的header axios get url headers authorization whr1 源码分析 lib core dispatchrequest js 44行 config headers utils merge config headers common config headers config method config headers 如何取消已经发送的请求 如何使用 import axios from axios 第一种取消方法 axios get url canceltoken new axios canceltoken cancel if 取消条件 cancel 取消日志 第二种取消方法 const canceltoken axios canceltoken const source canceltoken source axios get url canceltoken source token source cancel 取消日志 源码分析 cancel canceltoken js 11行 function canceltoken executor var resolvepromise this promise new promise function promiseexecutor resolve resolvepromise resolve var token this executor function cancel message if token reason return token reason new cancel message resolvepromise token reason lib adapters xhr js 159行 if config canceltoken config canceltoken promise then function oncanceled cancel if request return request abort reject cancel request null 取消功能的核心是通过canceltoken内的 this promise new promise resolve resolvepromise resolve 得到实例属性 promise 此时该 promise 的状态为 pending 通过这个属性 在 lib adapters xhr js 文件中继续给这个 promise 实例添加 then 方法 xhr js 文件的159行 config canceltoken promise then message request abort 在 canceltoken 外界 通过 executor 参数拿到对 cancel 方法的控制权 这样当执行 cancel 方法时就可以改变实例的 promise 属性的状态为 rejected 从而执行 request abort 方法达到取消请求的目的 上面第二种写法可以看作是对第一种写法的完善 因为很多是时候我们取消请求的方法是用在本次请求方法外 例如 发送a b两个请求 当b请求成功后 取消a请求 第1种写法 let source axios get aurl canceltoken new axios canceltoken cancel source cancel axios get burl then source b请求成功了 第2种写法 const canceltoken axios canceltoken const source canceltoken source axios get aurl canceltoken source token axios get burl then source cancel b请求成功了 相对来说 我更推崇第1种写法 因为第2种写法太隐蔽了 不如第一种直观好理解 发现的问题 lib adapters xhr js文件中 oncanceled方法的参数不应该叫message么 为什么叫cancel lib adapters xhr js文件中 oncanceled方法里 reject里应该将config信息也传出来 跨域携带cookie 如何使用 import axios from axios axios defaults withcredentials true 源码分析 我们在 用户配置的config是怎么起作用的 一节已经介绍了config在axios项目里的传递过程 由此得出 我们通过 axios defaults withcredentials true 做的配置 在 lib adapters xhr js 里是可以取到的 然后通过以下代码配置到xhr对象项 var request new xmlhttprequest lib adapters xhr js if config withcredentials request withcredentials true 超时配置及处理 如何使用 import axios from axios axios defaults timeout 3000 源码分析 adapters xhr js request timeout config timeout adapters xhr js 通过createerror方法 将错误信息合为一个字符串 request ontimeout function handletimeout reject createerror timeout of config timeout ms exceeded config econnaborted request axios库外如何添加超时后的处理 axios catch error const message error if message indexof timeout 1 超时处理 改写验证成功或失败的规则validatestatus 自定义http状态码的成功 失败范围 如何使用 import axios from axios axios defaults validatestatus status status 200 status 300 源码分析 在默认配置中 定义了默认的http状态码验证规则 所以自定义 validatestatus 其实是对此处方法的重写 lib defaults js var defaults validatestatus function validatestatus status return status 200 status 300 axios是何时开始验证http状态码的 lib adapters xhr js var request new xmlhttprequest var loadevent onreadystatechange lib adapters xhr js 每当 readystate 改变时 就会触发 onreadystatechange 事件 request loadevent function handleload if request request readystate 4 xdomain return 省略代码 var response ie sends 1223 instead of 204 https github com axios axios issues 201 status request status 1223 204 request status config config settle resolve reject response 省略代码 lib core settle js function settle resolve reject response 如果我们往上捣一捣就会发现 config对象的validatestatus就是我们自定义的validatestatus方法或默认的validatestatus方法 var validatestatus response config validatestatus validatestatus验证通过 就会触发resolve方法 if response status validatestatus validatestatus response status resolve response else reject createerror request failed with status code response status response config null response request response 总结 axios这个项目里 有很多对js使用很巧妙的地方 比如对promise的串联操作 当然你也可以说这块是借鉴很多异步中间件的处理方式 让我们可以很方便对请求前后的各种处理方法的流程进行控制 很多实用的小优化 比如请求前后的数据处理 省了程序员一遍一遍去写json xxx了 同时支持了浏览器和node两种环境 对使用node的项目来说无疑是极好的 总之 这个能够在github斩获42k 截止2018 05 27 的star 实力绝不是概的 值得好好交交心 about axios实例应用及源码剖析 xhr篇 走心教程 topics xhr http xmlhttprequest ajax axios axios promise xhr resources readme license mit license uh ...
|