iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >使用axios怎么一个自定义适配器adapter
  • 870
分享到

使用axios怎么一个自定义适配器adapter

2023-06-15 02:06:49 870人浏览 泡泡鱼
摘要

使用axiOS怎么一个自定义适配器adapter?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1. 适配器要实现的功能我们在基于 axios 实现额外的数据模块时,应当与

使用axiOS怎么一个自定义适配器adapter?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

1. 适配器要实现的功能

我们在基于 axios 实现额外的数据模块时,应当与 axios 的模式进行对齐。因此在返回的数据格式上,实现的功能上尽量保持一致。

1.1 promise 和工具

所有的适配均应当实现为 Promise 方式。

而且,有些功能的实现,axios 将其下放到了适配器中自己进行实现,例如

  • url 的拼接:即 baseURL 和 url 的拼接,若存在 baseURL 且 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 实例添加一个属性:

module.exports = 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,        };    };    return error;};

可以看到,除了正常的错误信息外,还加入了很多别的属性,例如 request, response, 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 settle from 'axios/lib/core/settle';import createError from 'axios/lib/core/createError';

然后直接使用就行了,不用再进行二次开发

1.3 超时设置

我们不能无限地等待第三方服务的响应,如果第三方服务无响应或者响应时间过长,应当适时的终止掉。在 axios 中,前端使用了XMLHttpRequest,在 node 端使用了http,来实现接口的请求,两者都有超时的设定,可以设置 timeout 字段来设置超时的时间,自动取消当前的请求。

像有的发起的请求,自己并没有超时的设定,例如 jsonp,是用创建一个 script 标签来发起的请求,这个请求必须等到服务器有响应才会终止(成功或者失败)。这时,就需要我们自己用一个setTimeout来模拟了,但这样,即使返回给业务层说“超时了,已取消当前请求”,但实际上请求还在,只不过若超过规定时间,只是不再执行对应的成功操作而已。

1.4 主动取消请求

我们也会有很多并没有到超时时间,就需要主动取消当前请求的场景,例如在请求返回之前就切换了路由;上次请求还没响应前,又需要发出新的请求等。都需要主动地取消当前请求。

axios 中已经提供了取消请求的功能,我们只需要按照规则接入即可。我们来看下 XMLHttpRequest 请求器中是怎么取消请求的,在写自定义请求器时也可以照理使用。

在lib/adapters/xhr.js#L158中:

// 若config中已经配置了cancelTokenif (config.cancelToken) {    // Handle cancellation    // 若在外城执行了取消请求的方法,则这里将当前的请求取消掉    config.cancelToken.promise.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 Promise((resolve, reject) => {        // 是否已取消当前操作        // 因jsonp没有主动取消请求的方式        // 这里使用 isAbort 来标识        let isAbort = false;        // 定时器标识符        let timer = null;        // 执行方法的名字,        const callbackName = `jsonp${Date.now()}_${Math.random()            .toString()            .slice(2)}`;        // 这里假设已经实现了baseURL和url的拼接方法        const fullPath = buildFullPath(config.baseURL, config.url);        // 这里假设已经实现了url和参数的拼接方法        // 不太一样的地方在于,jsonp需要额外插入一个自己的回调方法        const url = buildURL(            fullPath,            {                ...config.params,                ...{ [config.jsonpCallback || 'callback']: callbackName },            },            config.paramsSerializer        );        // 创建一个script标签        let script = document.createElement('script');        // 成功执行操作后        function remove() {            if (script) {                script.onload = script.onerror = null;                // 移除script标签                if (script.parentNode) {                    script.parentNode.removeChild(script);                }                // 取消定时器                if (timer) {                    clearTimeout(timer);                }                script = null;            }        }        // 成功请求后        window[callbackName] = (data) => {            // 若已需要请求,则不再执行            if (isAbort) {                return;            }            // 返回的格式            const response = {                status: 200,                statusText: 'ok',                config,                request: script,                data: data,            };            remove();            // 实际上这里上一个settle操作,会额外判断是否是合理的status状态            // 若我们在config.validateStatus中设置404是合理的,也会进入到resolve状态            // 但我们这里就不实现这个了            // settle(resolve, reject, response);            resolve(response);        };        // 请求失败        script.onerror = function (error) {            remove();            reject(createError('Network Error', config, 404));        };        // 若设置了超时时间        if (config.timeout) {            timer = setTimeout(function () {                remove();                // 取消当前操作                isAbort = true;                reject(                    createError(                        'timeout of ' + config.timeout + 'ms exceeded',                        config,                        405                    )                );            }, config.timeout);        }        // 若定义了取消操作        if (config.cancelToken) {            config.cancelToken.promise.then(function () {                if (!script) {                    return;                }                remove();                isAbort = true;                reject(createError('Cancel Error', config, 404));            });        }        script.src = url;        const target =            document.getElementsByTagName('script')[0] || document.head;        target.parentNode && target.parentNode.insertBefore(script, target);    });};export default jsonpAdapter;

3. 将适配器添加到 axios 中

axios 的 config 提供了 adapter 字段让我们插入自己的适配器。使用自定义适配器又有两种情况:

完全只使用自定义的适配器;

在某种情况下使用自定义适配器,其他情况时还是使用 axios 自己的适配器。

第 1 种情况还好,只需要 return 自己适配器返回的结果结果即可;而第 2 种情况中,则有个小坑需要踩一下,我们这里也只讲解下第 2 种情况。我要把刚才实现的 jsonp 适配器添加到 axios 中,并且只在参数有fORMat=jsonp时才调用该适配器,其他还是用的 axios 提供的适配器。

import Axios from 'axios';import jsonpAdapter from './jsonpAdater';const request = Axios.create({    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(    'https://api.prize.qq.com/v1/newsapp/answer/share/oneQ?qID=506336',    options)    .then(function (response) {        console.log('jsonp response', response);    })    .catch(function (error) {        console.error('jsonp error', error);    });

使用 axios 默认的适配器发起请求。

// 使用axios默认的适配器发起请求request('https://api.prize.qq.com/v1/newsapp/answer/share/oneQ?qID=506336')    .then(function (response) {        console.log('axios response', response);    })    .catch(function (error) {        console.error('axios error', error);    });

关于使用axios怎么一个自定义适配器adapter问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网精选频道了解更多相关知识。

--结束END--

本文标题: 使用axios怎么一个自定义适配器adapter

本文链接: https://www.lsjlt.com/news/276797.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 使用axios怎么一个自定义适配器adapter
    使用axios怎么一个自定义适配器adapter?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1. 适配器要实现的功能我们在基于 axios 实现额外的数据模块时,应当与 ...
    99+
    2023-06-15
  • 如何实现axios的自定义适配器adapter
    目录1. 适配器要实现的功能1.1 promise 和工具1.2 响应的格式1.3 超时设置1.4 主动取消请求2. 编写自定义适配器3. 将适配器添加到 axios 中4. 总结1...
    99+
    2024-04-02
  • Android适配器(Adapter)的概念与自定义
    目录一、什么是适配器二、Adapter基本概念和继承关系三、自定义适配器实例1.文件结构2.xml内容3.java内容四、参考资料总结一、什么是适配器 在常见软件中,往往能看到列表...
    99+
    2024-04-02
  • 利用Kotlin编写一个Adapter适配器
    本篇文章给大家分享的是有关利用Kotlin编写一个Adapter适配器,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。具体方法如下:package com.example.adm...
    99+
    2023-05-31
    kotlin adapter
  • PHP适配器模式Adapter Pattern怎么使用
    本篇内容主要讲解“PHP适配器模式Adapter Pattern怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP适配器模式Adapter Pattern怎么使用”...
    99+
    2023-07-05
  • Adapter适配器模式怎么应用
    这篇文章主要讲解了“Adapter适配器模式怎么应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Adapter适配器模式怎么应用”吧! Adapter(...
    99+
    2024-04-02
  • 使用canvas怎么自定义一个头像功能
    使用canvas怎么自定义一个头像功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实现细节:因为你要对图片所在的区域进行截图,所以你得制作一张canvas,盖...
    99+
    2023-06-09
  • 使用Java如何自定义一个迭代器
    使用Java如何自定义一个迭代器?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。具体如下:编写自己的Iterator,实现Iterator接口,这里多说一句,实现Iterab...
    99+
    2023-05-31
    java 自定义 迭代器
  • node.js怎么自定义实现一个EventEmitter
    这篇文章主要介绍“node.js怎么自定义实现一个EventEmitter”,在日常操作中,相信很多人在node.js怎么自定义实现一个EventEmitter问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”n...
    99+
    2023-06-20
  • C++中使用FFmpeg适配自定义编码器的实现方法
    目录1 编码流程1.1 整体流程1.2 内部流程2 适配接口2.1 init、close2.2 option2.3 receive2.4 encode2.5 零拷贝的设计1 编码流程...
    99+
    2023-05-16
    C++ FFmpeg适配编码器 C++ FFmpeg自定义编码器
  • 怎么在java中自定义一个类加载器
    本篇文章为大家展示了怎么在java中自定义一个类加载器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。如果要使用自定义类加载器加载class文件,就需要继承java.lang.ClassLoader类...
    99+
    2023-05-30
    java
  • Android应用中怎么自定义一个菜单栏
    这期内容当中小编将会给大家带来有关Android应用中怎么自定义一个菜单栏,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。在android开发的过程中系统自带的菜单往往满足不了开发中的一些需求,比如说一排最...
    99+
    2023-05-31
    android roi
  • 怎么写一个Vue3的自定义指令
    本篇内容主要讲解“怎么写一个Vue3的自定义指令”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么写一个Vue3的自定义指令”吧!背景众所周知,Vue.js 的核心思想是数据驱动 + 组件化,通...
    99+
    2023-06-26
  • 怎么自定义一个jQuery扩展接口
    这篇文章给大家介绍怎么自定义一个jQuery扩展接口,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。jQuery是一款很优秀的轻量级JavaScript框架,有其独特的优点。很多Web开...
    99+
    2024-04-02
  • 怎么在Android中自定义一个控件
    怎么在Android中自定义一个控件?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。代码class SleepDayChart(context: Contex...
    99+
    2023-06-14
  • 详解怎么使用vue封装一个自定义日历组件
    执行这个方法之后,此时calendarProps的值为:4、根据日历属性生成日历日期的数据当我们已经知道本月第一天对应的周几索引值、本月一共有多少天和上个月一共有多少天这三个核心数据之后,就可以开始生成对应的日历数据了。思路如下:由于大部分...
    99+
    2023-05-14
    Vue.js 数据可视化 前端
  • 怎么在HTML5中自定义一个视频播放器
    这期内容当中小编将会给大家带来有关怎么在HTML5中自定义一个视频播放器,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。video对象兼容性写法<video controls>&nbs...
    99+
    2023-06-09
  • 使用Flex怎么实现一个自适应页面
    使用Flex怎么实现一个自适应页面?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Flex布局简介Flex英文为flexiable box,翻译为弹性盒子,Fle...
    99+
    2023-06-08
  • Spring Cloud中Feign怎么自定义配置与使用
    这篇文章主要介绍了Spring Cloud中Feign怎么自定义配置与使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring Cloud中Feign怎么自定义配置与使用文章都会有所收...
    99+
    2023-07-02
  • 怎么在android中自定义一个PagerAdapter方法
    这篇文章给大家介绍怎么在android中自定义一个PagerAdapter方法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。首先,如果继承pageradapter,至少必须重写下面的四个方法  &n...
    99+
    2023-05-30
    android pageradapter
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作