当前位置: 首页 > Web前端 > HTML

axios源码解读-网络请求

时间:2023-03-28 19:31:45 HTML

上一章我们介绍了axios源码解读-request。本章我们将介绍Axios中真正发起网络请求的部分,即dispatchRequest方法。dispatchRequest方法定义也比较简单(如下图所示)。第29行——取消请求让我们逐行分析每一行代码做了什么。第一个是第29行的取消请求。(下)throwIfCancellationRequested(config);这个动作不仅在发起正式请求前做一次,在请求成功和请求失败时也会做一次。只要取消请求,就不会进入成功或失败的回调处理。(如下图)throwIfCancellationRequested函数做的是检测请求是否取消,如果取消则抛出错误,阻止代码继续往下执行。(下)functionthrowIfCancellationRequested(config){if(config.cancelToken){//检测请求是否被取消,然后决定是否抛出错误config.cancelToken.throwIfRequested();}if(config.signal&&config.signal.aborted){//抛出错误thrownewCancel('canceled');}}当然,整套CancelToken的实现还是有些复杂(复杂的地方在于回调处理),有兴趣的可以单独说说这部分的处理,这里就不展开了。第35~40行——处理请求dataconfig.data=transformData.call(config,config.data,config.headers,config.transformRequest);这里使用了一个transformData方法,主要作用是合并数据,配置可以使用transformRequest方法进行合并(如下图)。transformData方法遍历传入的transformRequest方法,将data和headers作为transformRequest的入参,然后将返回结果复制到config.data中,作为最终请求发送的数据内容。第43~54行-合并请求标头config.headers=utils.merge(config.headers.common||{},config.headers[config.method]||{},config.headers);utils.forEach(['delete','get','head','post','put','patch','common'],functioncleanHeaderConfig(method){deleteconfig.headers[method];});上面的代码主要做了两件事:第一件事是将commonheaders(公共头文件)与对应方法的headers和原始headers进行合并;第二件事是在合并完成后删除多余的headers配置。第56~58行-发起一个真正的请求varadapter=config.adapter||默认值.适配器;returnadapter(config).then(functiononAdapterResolution(response){//...});这里使用的是配置好的适配器,其实就是请求的方式。比如这两个默认的请求方法在浏览器端运行时使用XMLHttpRequest,在Node端运行时使用http模块。知道这个配置能做什么吗?你可以在这里传入一个自定义的请求方法,比如在客户端使用fetch包来代替XMLHttpRequest。你也可以传入一个你这里封装好的mock方法,本地返回的json数据全部用于mock数据,不需要额外构建mock服务。......言归正传,我们来看看axios默认的两个adapter。本文将重点介绍客户端适配器——xhrAdapter。客户端适配器——xhrAdapter我们按照约定逐行解析客户端适配器——xhrAdapter。发起请求前的准备工作描述第16~18行收集请求数据信息(requestData)、请求头信息(requestHeaders)、返回体类型(responseType)第19~28行处理cancelToken,当请求完成时取消订阅释放内存;还有signal的处理,文档里已经没有看到了,应该也是abort请求用的。第30到32行删除了FormData请求的Content-Type请求头,允许浏览器自动设置请求头。设置身份验证信息首先,在第34行,为后续网络请求创建了一个XMLHttpRequest实例。然后在第37到41行,设置了HTTP基本认证的信息。从这一段中,我们可以学习到简单的HTTP基本认证认证知识。先对password进行encodeURLComponent转义编码,然后将username和password按照规则进行拼接,然后使用btoa将username和password转为base64编码。如果以后想自己做这种事情,可以翻到本章找到这部分的代码内容,再复制一遍。拼接请求url首先使用buildFullPath方法与完整的请求url进行拼接。(如下图所示),可见该方法不会为绝对路径(isAbsoluteURL())的url拼接baseURL。然后axios还使用buildURL方法将params参数拼接到url中——也就是我们常说的query参数。(下)functionbuildURL(url,params,paramsSerializer){/*eslintno-param-reassign:0*/if(!params){returnurl;}var序列化参数;如果(paramsSerializer){serializedParams=paramsSerializer(params);}elseif(utils.isURLSearchParams(params)){serializedParams=params.toString();}else{//...serializedParams=parts.join('&');}if(serializedParams){//...//这里将处理后的参数拼接到url中作为query查询参数url+=(url.indexOf('?')===-1?'?':'&')+序列化参数;}返回网址;};这就是为什么在使用axios时,GET方法的参数要设置在params字段中。然后,使用request.open方法发起请求。响应回调函数接下来就是比较核心的响应回调函数(如下图所示)。行号说明Line54获取所有响应头Line55获取响应内容Lines57~64设置promiseresolve内容,也就是你经常console.logitout那些东西你应该很熟悉了。设置完其他回调函数后,基本上就是设置了XMLHttpRequest对象的一些回调函数。(如下图所示)如果你是后来者,接触前端,可能对XMLHttpRequest实例的事件不是很清楚。您可以参考XMLHttpRequest文档。最后,发送请求。(如下)request.send(requestData);回到dispatchRequest从上面可以看出,dispatchRequest最终调用adapter后,得到了如下数据。{数据:responseData,status:request.status,statusText:request.statusText,headers:responseHeaders,config:config,request:request};那我们再看看dispatchRequest内部是如何处理这块数据的。(如下图所示)行号说明59/72行处理被CancelToken取消的请求。如果取消请求,则不会继续执行62~67行。通过transformResponse对响应结果进行转换,得到处理后的响应数据。第69行将返回响应结果。这样,整个axios的请求流程就梳理好了。我们画个流程图来梳理一下。(如下图)Node端的adapter这里就不做说明了。与客户端的区别主要在于以下几点:Node的http模块用于发起请求。可以通过proxy设置代理服务器,请求会发送到代理服务器。总结的很好,我们对axios源码的解读到此结束。可以看出,axios虽然是目前最流行最强大的网络请求框架,但是源码看起来还是比较清晰易读的。建议大家按照文中思路自行阅读。下一章我们将实现一个简单的axios框架,包括axios的一些核心功能,结束axios源码解读系列。最后一点,如果你已经看过这篇文章,希望你在离开前点赞~你的点赞是对作者最大的鼓励,也会让更多人看到这篇文章!如果您觉得本文对您有帮助,请帮忙点亮github上的star,鼓励一下!