返回顶部
首页 > 资讯 > 精选 >使用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://lsjlt.com/news/276797.html(转载时请注明来源链接)

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

猜你喜欢
  • 使用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自定义viewgroup 使用adapter适配数据(6)
    在自定义viewgroup(5)://www.jb51.net/article/100639.htm的基础上,添加使用adapter来适配数据,这样更加的方便,这里只是使用ad...
    99+
    2022-06-06
    数据 adapter Android
  • 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
  • Android之自定义实现BaseAdapter(通用适配器一)
    通过前面的优化布局之后,我们接着来讲如何打造一个通用的适配器,那么通用适配器能干吗呢?很简单,减少我们对代码的书写,下面开始上代码了。 MyAdapter.java publ...
    99+
    2022-06-06
    自定义 baseadapter 通用 Android
  • 使用canvas怎么自定义一个头像功能
    使用canvas怎么自定义一个头像功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实现细节:因为你要对图片所在的区域进行截图,所以你得制作一张canvas,盖...
    99+
    2023-06-09
  • 使用Java如何自定义一个迭代器
    使用Java如何自定义一个迭代器?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。具体如下:编写自己的Iterator,实现Iterator接口,这里多说一句,实现Iterab...
    99+
    2023-05-31
    java 自定义 迭代器
  • Android之自定义实现BaseAdapter(通用适配器二)
    在上一篇通用适配器一中,我们已经把ViewHolder抽取为了一个通用的持有类,极大程度上减少了我们对代码的书写,现在开始在那样的基础上在此抽取,从而达到更优。先回顾上一篇中的...
    99+
    2022-06-06
    自定义 baseadapter 通用 Android
  • Android之自定义实现BaseAdapter(通用适配器三)
    在上一篇中,我们说过,在setData中如果有很多控件的话,我们还是要在该方法中写入很多代码,为了降低开发的方便性,本次就在此基础上再一次优化。实现原理是这样的,每次在setD...
    99+
    2022-06-06
    自定义 baseadapter 通用 Android
  • Android编程中常用适配器及自定义适配器用法实例分析
    本文实例讲述了Android编程中常用适配器及自定义适配器用法。分享给大家供大家参考,具体如下: 一、适配器. 顾名思义,就是把一些数据给弄得适当,适合以便于在View上显示。...
    99+
    2022-06-06
    自定义 Android
  • 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
  • 怎么自定义一个jQuery扩展接口
    这篇文章给大家介绍怎么自定义一个jQuery扩展接口,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。jQuery是一款很优秀的轻量级JavaScript框架,有其独特的优点。很多Web开...
    99+
    2024-04-02
  • 怎么在Android中自定义一个控件
    怎么在Android中自定义一个控件?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。代码class SleepDayChart(context: Contex...
    99+
    2023-06-14
  • 怎么写一个Vue3的自定义指令
    本篇内容主要讲解“怎么写一个Vue3的自定义指令”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么写一个Vue3的自定义指令”吧!背景众所周知,Vue.js 的核心思想是数据驱动 + 组件化,通...
    99+
    2023-06-26
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作