如何实现axios的自定义适配器adapter

更新时间:2023-05-17 12:22:59 阅读: 评论:0

如何实现axios的⾃定义适配器adapter
⽬录
1. 适配器要实现的功能
1.1 promi 和⼯具
1.2 响应的格式
1.3 超时设置
1.4 主动取消请求
2. 编写⾃定义适配器
3. 将适配器添加到 axios 中
4. 总结
1. 适配器要实现的功能
我们在基于 axios 实现额外的数据模块时,应当与 axios 的模式进⾏对齐。因此在返回的数据格式上,实现的功能上尽量保持⼀致。
1.1 promi 和⼯具
所有的适配均应当实现为 Promi ⽅式。
⽽且,有些功能的实现,axios 将其下放到了适配器中⾃⼰进⾏实现,例如
url 的拼接:即 baURL 和 url 的拼接,若存在 baURL 且 url 为相对路径,则进⾏拼接,否则直接使⽤ url;
参数的拼接:若是 get 请求,需要⾃⾏将 object 类型拼接为 url 参数的格式并与 url 拼接完成;
这是⾃⼰需要实现的两个基本的⼯具⽅法。
1.2 响应的格式
这⾥我们要注意到请求接⼝正常和异常的格式。
接⼝正常时:
const result = {
status: 200, // 接⼝的http 状态
statusText: 'ok',
config: 'config', // 传⼊的config配置,原样返回即可,⽅便在响应拦截器和响应结果中使⽤
data: {}, // 真实的接⼝返回结果
};
接⼝异常时,我们可以看下 axios 源码中对错误信息的处理createError,enhanceError(createError 中调⽤了enhanceError),⾸先会创建⼀个 error 实例,然后给这个 error 实例添加⼀个属性:
if (code) {
}
error.isAxiosError = true;
return {
// Standard
message: ssage,
name: this.name,
// Microsoft
description: this.description,
number: this.number,
// Mozilla
fileName: this.fileName,
lineNumber: this.lineNumber,
columnNumber: lumnNumber,
stack: this.stack,
// Axios
config: fig,
code: de,
};
};
return error;
};
可以看到,除了正常的错误信息外,还加⼊了很多别的属性,例如 request, respon, config 等。这⾥我们在⾃⼰实现适配器时,最好也要这样统⼀编写,⽅便更上层的业务层统⼀处理,避免为单独的适配器进⾏特殊处理。
关于 1.1 和 1.2 中的内容,若不进⾏打包编译,则需要⾃⼰实现。若还要通过 webpack 等打包⼯具编译⼀下的,可以直接引⽤ axios 中的⽅法,不⽤⾃⼰实现了,参考官⽅基于 axios 实现的mock-axios。例如:
import axios from 'axios';
import buildURL from 'axios/lib/helpers/buildURL';
import isURLSameOrigin from 'axios/lib/helpers/isURLSameOrigin';
import btoa from 'axios/lib/helpers/btoa';
import cookies from 'axios/lib/helpers/cookies';
import ttle from 'axios/lib/core/ttle';
import createError from 'axios/lib/core/createError';
然后直接使⽤就⾏了,不⽤再进⾏⼆次开发。
1.3 超时设置
眼睁睁造句
我们不能⽆限地等待第三⽅服务的响应,如果第三⽅服务⽆响应或者响应时间过长,应当适时的终⽌掉。在 axios 中,前端使⽤了XMLHttpRequest,在 node 端使⽤了http,来实现接⼝的请求,两者都有超时的设定,可以设置 timeout 字段来设置超时的时间,⾃动取消当前的请求。
像有的发起的请求,⾃⼰并没有超时的设定,例如 jsonp,是⽤创建⼀个 script 标签来发起的请求,这个请求必须等到服务器有响应才会终⽌(成功或者失败)。这时,就需要我们⾃⼰⽤⼀个tTimeout来模拟了,但这样,即使返回给业务层说“超时了,已取消当前请求”,但实际上请求还在,只不过若超过规定时间,只是不再执⾏对应的成功操作⽽已。
1.4 主动取消请求
南通绿博园我们也会有很多并没有到超时时间,就需要主动取消当前请求的场景,例如在请求返回之前就切换了路由;上次请求还没响应前,⼜需要发出新的请求等。都需要主动地取消当前请求。
axios 中已经提供了取消请求的功能,我们只需要按照规则接⼊即可。我们来看下 XMLHttpRequest 请求器中是怎么取消请求的,在写⾃定义请求器时也可以照理使⽤。
在lib/adapters/xhr.js#L158中:
// 若config中已经配置了cancelToken
if (config.cancelToken) {
// Handle cancellation
// 若在外城执⾏了取消请求的⽅法,则这⾥将当前的请求取消掉
config.cancelToken.promi.then(function onCanceled(cancel) {
if (!request) {
return;
}
// xhr中使⽤abort⽅法取消当前请求
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
我们在写⾃⼰的适配器时,也可以将这段拷贝过去,将内部取消的操作更换为⾃⼰的即可。
到这⾥,若把上⾯的功能都实现了,就已经完成了⼀个标准的适配器了。
2. 编写⾃定义适配器
每个⼈需要的适配器肯定也不⼀样,复杂度也不⼀样,例如有的想接⼊⼩程序的请求,我⾃⼰想接⼊客户端⾥提供的数据请求⽅式等。我们这⾥只是通过实现⼀个简单的jsonp适配器来讲解下实现⽅式。
我们以 es6 的模块⽅式来进⾏开发。所有的实现均在代码中进⾏了讲解。// 这⾥的config是axios⾥所有的配置
const jsonpAdapter = (config) => {
仁者见仁什么意思return new Promi((resolve, reject) => {
// 是否已取消当前操作
// 因jsonp没有主动取消请求的⽅式
// 这⾥使⽤ isAbort 来标识
let isAbort = fal;
// 定时器标识符
let timer = null;
// 执⾏⽅法的名字,
const callbackName = `jsonp${w()}_${Math.random()
.toString()
.slice(2)}`;
// 这⾥假设已经实现了baURL和url的拼接⽅法
const fullPath = buildFullPath(config.baURL, config.url);
// 这⾥假设已经实现了url和参数的拼接⽅法
// 不太⼀样的地⽅在于,jsonp需要额外插⼊⼀个⾃⼰的回调⽅法
const url = buildURL(
fullPath,
{
...config.params,
...{ [config.jsonpCallback || 'callback']: callbackName },
},
config.paramsSerializer
);
// 创建⼀个script标签
let script = ateElement('script');
// 成功执⾏操作后
function remove() {
if (script) {
// 移除script标签
if (script.parentNode) {
veChild(script);
}
// 取消定时器
if (timer) {
clearTimeout(timer);
}
script = null;
}
}
// 成功请求后
window[callbackName] = (data) => {
/
/ 若已需要请求,则不再执⾏
if (isAbort) {
白茶冲泡方法return;
}
// 返回的格式
const respon = {
status: 200,
statusText: 'ok',
config,
request: script,
data: data,
};
remove();北海道在哪里
// 实际上这⾥上⼀个ttle操作,会额外判断是否是合理的status状态
// 若我们在config.validateStatus中设置404是合理的,也会进⼊到resolve状态
// 但我们这⾥就不实现这个了
// ttle(resolve, reject, respon);
resolve(respon);
};
// 请求失败
领带品牌r = function (error) {
remove();
reject(createError('Network Error', config, 404));
};
// 若设置了超时时间
if (config.timeout) {
timer = tTimeout(function () {
remove();
// 取消当前操作
isAbort = true;
reject(
createError(
'timeout of ' + config.timeout + 'ms exceeded',
config,
405
)
);
}, config.timeout);
}
// 若定义了取消操作
if (config.cancelToken) {
config.cancelToken.promi.then(function () {
if (!script) {
return;
}
remove();
isAbort = true;
reject(createError('Cancel Error', config, 404));
});
蹭课}
script.src = url;
const target =
target.parentNode && target.parentNode.inrtBefore(script, target);
});
};
export default jsonpAdapter;
3. 将适配器添加到 axios 中
axios 的 config 提供了 adapter 字段让我们插⼊⾃⼰的适配器。使⽤⾃定义适配器⼜有两种情况:
1.完全只使⽤⾃定义的适配器;
2.在某种情况下使⽤⾃定义适配器,其他情况时还是使⽤ axios ⾃⼰的适配器。
第 1 种情况还好,只需要 return ⾃⼰适配器返回的结果结果即可;⽽第 2 种情况中,则有个⼩坑需要踩⼀下,我们这⾥也只讲解下第 2 种情况。我要把刚才实现的 jsonp 适配器添加到 axios 中,并且只在参数有format=jsonp时才调⽤该适配器,其他还是⽤的 axios 提供的适配器。
import Axios from 'axios';
import jsonpAdapter from './jsonpAdater';
const request = ate({
adapter: (config) => {
if (config?.params?.format === 'jsonp') {
return jsonpAdapter(config);
}
// 这⾥需要将config.adapter设置为空
// 否则会造成⽆限循环
return defaultAxios({ ...config, ...{ adapter: undefined } });
},
});
使⽤⾃定义的适配器 jsonp 发起请求。
// 使⽤⾃定义的适配器jsonp发起请求
var options = {
params: {
format: 'jsonp',
},
};
request(
'api./v1/newsapp/answer/share/oneQ?qID=506336',
options
)
.then(function (respon) {
console.log('jsonp respon', respon);
})
.catch(function (error) {
<('jsonp error', error);
});
使⽤ axios 默认的适配器发起请求。
// 使⽤axios默认的适配器发起请求
request('api./v1/newsapp/answer/share/oneQ?qID=506336')
.then(function (respon) {
console.log('axios respon', respon);
})
.catch(function (error) {
<('axios error', error);
});
已知数4. 总结
这⾥,我们就已经实现了⼀个⾃定义适配器了,在满⾜⼀定条件时可以触发这个适配器。通过这个思路,我们也可以实现⼀个⾃定义的 mock ⽅法,例如当参数中包含format=mock时则调⽤ mock 接⼝,否则就正常请求。
以上就是如何实现axios的⾃定义适配器adapter的详细内容,更多关于axios⾃定义适配器adapter的资料请关注其它相关⽂章!

本文发布于:2023-05-17 12:22:59,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/667591.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:请求   适配器   实现   取消   需要   定义   响应   发起
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图