Day 5 登录页及路由 (三) 基于axios的API调用

系列文章目录

本系列记录一下通过Abp搭建后端,Vue+Element UI Plus搭建前端,实现一个小型项目的过程。

  • Day 1 Vue 页面框架
  • Day 2 Abp框架下,MySQL数据迁移时,添加表和字段注释
  • Day 3 登录页以及路由 (一)
  • Day 4 登录页以及路由 (二)Vue状态管理

文章目录

  • 目录

    系列文章目录

    文章目录

    前言

    一、axios

    二、封装还是不封装,这是个问题

    1. 封装的目的

    2. 怎么封装

    3. 到底要不要封装


前言

作为前后端分离的系统,请求后端API是一个必不可少的工作,本文就介绍了Vue中调用后端API的基础内容。


一、axios

Vue官方推荐使用axios来进行网络请求,于是先到axios的官网上看了一遍文档,其介绍是这样的:

Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

大致看了一下官方文档,发现功能已经很齐全了,唯一需要处理的就是针对特定系统的配置性处理。程序员之魂开始燃烧,封印术已经按捺不住了。

二、封装还是不封装,这是个问题

1. 封装的目的

老套路,先看看别人怎么做的(程序员的事情,怎么能叫抄呢 🤣)。搜索一下,有做简单封装的(比如 这个 ),有做复杂封装的(比如这个和这个),同时评论区也有人疑惑为何要封装,是不是和axios背道而驰。

首先,封装的目的,总结下来大致有这么几个:

  1.  统一请求头。大部分项目对应的后端,需要统一请求头,比如app,version,token之类的。既然是统一,那天然的就应该是放在封装层里面。
  2. 错误处理。根据API返回结果,或者更底层一点,根据HttpStatus来进行通用的错误处理。啊哈,通用,懂了把。
  3. 重试及取消操作。在网络世界,不通是常见的“偶发”问题。或者是连接失败,或者是服务器错误,或者是太阳黑子影响,总之,反应到页面上就是无法访问。然后刷新一下就神奇的好了。另外,操作响应时间不固定,性急的人往往会连击,而响应不一定是按请求顺序返回,或者直接不返回。不做处理的话,容易造成数据混乱,页面卡死之类的。这个时候取消一下前面的请求,让页面只对最后一个请求结果进行处理,会简化处理逻辑。同样,这个“应该”也是一个统一处理。
  4. 开发过程中的配置。设置接口请求前缀:根据开发、测试、生产环境的不同,前缀需要加以区分。我的理解这是一个伪需求, axios本身的baseUrl就是干这个的。
  5. 觉得axios是第三方库,对项目而言需要隔离一下,以备将来换成别的库。这个就见仁见智了,解耦到这个程度,还是需要一些勇气的。另外,你确定不是在重复设计axios?
  6. 就是单纯不封装不舒服,不服来战

2. 怎么封装

具体封装的手段大致有两个:

  1. 依赖拦截器,无论是请求拦截器还是响应拦截器,都是axios提供的扩展点。
  2. 封装常用代码为方法。即把get、post等常用请求方法,再封装一次。这个我以为仅限于项目中对这些方法有特定需要的。因为axios本身就有别名方法,够满足大部分需要了。

3. 到底要不要封装

看了一圈下来,结合官方文档,我感觉二次封装有必要,但过度封装就没有必要了,搭建一个架子,把基本目标实现了就可以了,其它的后续再根据需求调整,渐进式开发嘛。

其实,从后端开发的角度来看,封装axios就和封装WebRequest,HttpClient之类的一样,根据实际需要来就行。要克制,过度设计有害健康。

另外,大部分文章都提到了将实际api的调用封装起来,放到单独的文件中去(比如api\xxxManage.ts)。这个我赞成,和后端服务层或数据访问层的作用一样。这么看,axios就和DBDriver一样,属于偏底层的库(当然,它的底层是XmlHttpRquest 和 node.js http 模块)。

基础研究到此为止,开始重复发明轮子。

三、实际操作

1. 代码结构

创建 src/api 文件夹,下面创建 index.ts 文件,axios的封装代码就写在这里了。然后针对不同的领域,建立不同的api封装文件。比如 login.ts 就封装登录相关api,提供给LoginView使用。

2. 调用端代码

参照TDD的方式,先写最顶层调用端代码

src/view/LoginView.vue

async function fakeLogin(event: Event) {
    //currentUser.setToken("faked login token")
    const loginRequest: Login.LoginRequest = { username: "test", password: "pw" }
    const loginResponse: Login.LoginResponse = await login(loginRequest)
    currentUser.setToken(loginResponse.access_token)
    currentUser.setUserInfo({ name: loginResponse.name })
}

伪代码一路到底,这里利用了语法糖, await还是很甜的。

然后定义login api 的封装接口,这里没有想好login方法是否要放入Login命名空间,暂时先这样吧。

src/api/login.ts

// 登录模块
export namespace Login {
  export interface LoginRequest {
    username: string
    password: string
  }
  export interface LoginResponse {
    access_token: string
    name:string
  }  
}

export const login = async (params: Login.LoginRequest) => {
    console.log("call async login.")
    const response:LoginResponse = { access_token:"token", name:"test user"}
    return response
}

测试一下,看看效果,点击Fake Login按钮后:

3. API 接入实现

先做基础配置工作,src/api/index.ts

import axios, { AxiosError } from 'axios'
import type { InternalAxiosRequestConfig } from 'axios'

import { BASE_URL } from '@/config'
import { useCurrentUserStore } from '@/stores/currentUser'

const instance = axios.create({
  baseURL: BASE_URL,
  timeout: 3000,  
})

instance.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 当前用户已登录的情况下,添加Authorization请求头
    const userStore = useCurrentUserStore()
    if (userStore.token != '') {
      if (config.headers && typeof config.headers.set === 'function') {
        config.headers.set('Authorization', userStore.token)
      }
    }
    return config
  },
  (error: AxiosError) => {
    return Promise.reject(error)
  }
)

export default instance

到这个阶段,暂时只是添加token到请求头里,其实这个都算早的,只是为了使用下拦截器,而且确实也是后面需要的功能,所以先写下来。后面错误处理还没有弄,这个需要结合页面表现再看。

另外就是BASE_URL直接使用了config的配置,关于环境的切换,发布时直接更改这个也不是很麻烦,暂时就先这样了。

重写 src/api/login.ts

import http from '@/api'
import type { Login, ResultDTO } from './interfaces'

export const login = async (
  params: Login.LoginRequest
): Promise<ResultDTO<Login.LoginResponse>> => {
  const { data } = await http.post('/api/account/login', params)
  return data
}

把请求和响应移到 interfaces文件中,统一管理了。这个只是一个习惯,看将来大概会从什么角度来阅读代码。所有请求放到一个文件,方便上手就能看到整体。放到接近使用的地方,比如login.ts中,则可以在使用的地方就知道具体含义,不过IDE的Go to definition功能也是很好用的。

interfaces里面还包括了后端响应基类,没有采用REST的推荐,自定义了Code,具体代码如下:

src/api/interface.ts

/** API响应 */
export interface ResultBase {
  /** 响应代码 */
  code: string
  /** 消息 */
  message: string
  /** 是否成功 */
  success: boolean
}
/** API响应 */
export interface ResultDTO<T> extends ResultBase {
  /** 数据 */
  data: T
}

// 登录模块
export namespace Login {
    /** 登录请求 */
  export interface LoginRequest {
    /** 用户名 */
    username: string
    /** 密码 */
    password: string
  }
  /** 登录响应账号信息 */
  export interface LoginResponse {
    /** Token */
    token: string
    /** 用户昵称 */
    nickname: string
  }
}

四、总结

前面搞了一大堆,实际代码没有多少,另外错误处理也还没有弄,但是理清了思路。这里有一个点,就是src/api/login.ts 这个文件是否有必要,因为就是一行代码,封装成函数似乎有点重复且繁复。暂时留在这里也是为了错误处理,还没有思考具体错误处理是留在这里,还是放到view层,或者直接在 axios 封装代码里,通过响应拦截器处理。各有各的优缺点。等先把页面样式写好,再看看写到哪里比较合适。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/115328.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis学习系统(持续更新中)

RedisExample 课程介绍 目标是提供一个高效、可靠的学习和实践Redis的环境。我们将通过搭建Redis集群、实现缓存数据的持久化存储、制定缓存数据的淘汰策略以及同步缓存数据等步骤来深入了解和学习Redis的特性和功能。通过这个项目&#xff0c;你可以掌握Redis的核心概念和技…

网络安全演练(一句话木马)

在享受互联网带来的便利的同时&#xff0c;也充满了各种网络安全风险&#xff0c;本文通过搭建实验环境&#xff0c;演示一句话木马获取主机权限。 演示环境 服务端&#xff1a;安装LAMP环境&#xff0c;部署web网站&#xff0c;上传一句话木马文件 客户端&#xff1a;安装A…

【Hydro】不同潜在蒸散发计算方法说明

目录 一、基本概念说明蒸发 E E E、散发 T T T、蒸散发 E T ET ET潜在蒸散发 E T p ET_p ETp​、参考作物蒸散发 E T 0 ET_0 ET0​、实际蒸散发 E T a ET_a ETa​及作物实际蒸散发 E T c ET_c ETc​ 二、部分潜在蒸散发估算方法表三、SWAT模型中的潜在蒸散发计算Penman-Monteit…

尚硅谷大数据项目《在线教育之实时数仓》笔记005

视频地址&#xff1a;尚硅谷大数据项目《在线教育之实时数仓》_哔哩哔哩_bilibili 目录 第9章 数仓开发之DWD层 P031 P032 P033 P034 P035 P036 P037 P038 P039 P040 第9章 数仓开发之DWD层 P031 DWD层设计要点&#xff1a; &#xff08;1&#xff09;DWD层的设计依…

提示3D标题编辑器仍在运行怎么解决,以及3D标题编辑器怎么使用

在进行视频剪辑时&#xff0c;尤其是剪辑一些带有文字的开场视频&#xff0c;一般都会使用具有立体效果的3D标题&#xff0c;这样制作出来的视频效果不仅好看&#xff0c;还非常的炫酷&#xff0c;但是对于一些刚刚开始接触视频剪辑的小伙伴来说&#xff0c;可能对3D标题还不是…

【深度学习基础】Pytorch框架CV开发(2)实战篇

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

VMware 虚拟机安装 CentOS 7

CentOS 7 1. 下载CentOS 7 iso镜像 Index of /centos/7.9.2009/isos/x86_64/ 2. Vmware安装CentOS 7 安装教程&#xff1a; 超详细VMware CentOS7(最小安装)安装教程_虚拟机最小化安装-CSDN博客 【精选】VMware 安装 Centos7 详细过程_vm虚拟机安装centos7_expectation Fu…

VBA快速动态考勤统计

实例需求&#xff1a;某公司的上下班打卡记录如下所示&#xff0c;其中Table_In为上班打卡记录&#xff0c;Table_Out为下班打卡记录。 现在需要根据日期整理为如下格式的考勤表。需要注意如下几点&#xff1a; 每天的打卡次数不确定最后一列Total/Day统计该天的出勤总时长&a…

04.Oracle的体系架构

Oracle的体系架构 一、主要组件二、Oracle的实例 一、主要组件 下面是一张网图&#xff0c;大家可以了解一下oracle的体系架构 Oracle数据库的体系架构可以分为以下几个主要组件&#xff1a;实例&#xff08;Instance&#xff09;、数据库&#xff08;Database&#xff09;、…

【React】03.脚手架的进阶应用

文章目录 暴露webpack配置暴露前后的区别config文件夹&#xff1a;scripts文件夹&#xff1a;package.json 常见的配置修改1.把sass改为less2.配置别名3.修改域名和端口号4.修改浏览器兼容5.处理Proxy跨域 2023年最新珠峰React全家桶【react基础-进阶-项目-源码-淘系-面试题】 …

JVM 内存和 GC 算法

文章目录 内存布局直接内存执行引擎解释器JIT 即时编译器JIT 分类AOT 静态提前编译器&#xff08;Ahead Of Time Compiler&#xff09; GC什么是垃圾为什么要GC垃圾回收行为Java GC 主要关注的区域对象的 finalization 机制GC 相关算法引用计数算法&#xff08;Reference Count…

Iceberg 基础知识与基础使用

1 Iceber简介 1.1 概述 为了解决数据存储和计算引擎之间的适配的问题&#xff0c;Netflix开发了Iceberg&#xff0c;2018年11月16日进入Apache孵化器&#xff0c;2020 年5月19日从孵化器毕业&#xff0c;成为Apache的顶级项目。 Iceberg是一个面向海量数据分析场景的开放表格…

Cross-Entropy Loss(多分类损失函数)

文章目录 1. 网络输出output&#xff1a;score2. Cross-Entropy Loss(多分类损失函数) 1. 网络输出output&#xff1a;score 2. Cross-Entropy Loss(多分类损失函数) 先用softmax function把score 变成 probabilities。再用交叉熵损失函数来进行Loss的计算

设计模式(23)解释器模式

一、介绍&#xff1a; 1、定义&#xff1a;解释器(Interpreter)模式是一种对象的行为模式。给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;这个解释器使用该表示来解释语言中的句子。 2、组成结构&#xff1a; &#xff08;1&…

C#__对Json文件的解析和序列化

Json: 存储和交换文本信息的语法。&#xff08;类似XML&#xff0c;语法独立&#xff09; 一种轻量级的数据交换格式。&#xff08;更小&#xff0c;更快&#xff0c;更易解析&#xff09; 语法规则: 数据在键值对里面&#xff0c;数据由逗号分隔开。 …

android display 杂谈(三)WMS

用来记录学习wms&#xff0c;后续会一点一点更新。。。。。。 代码&#xff1a;android14 WMS是在SystemServer进程中启动的 在SystemServer中的main方法中&#xff0c;调用run方法。 private void run() { // Initialize native services.初始化服务&#xff0c;加载andro…

Azure 机器学习 - 无代码自动机器学习的预测需求

了解如何在 Azure 机器学习工作室中使用自动化机器学习在不编写任何代码行的情况下创建时序预测模型。 此模型将预测自行车共享服务的租赁需求。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕…

面试算法47:二叉树剪枝

题目 一棵二叉树的所有节点的值要么是0要么是1&#xff0c;请剪除该二叉树中所有节点的值全都是0的子树。例如&#xff0c;在剪除图8.2&#xff08;a&#xff09;中二叉树中所有节点值都为0的子树之后的结果如图8.2&#xff08;b&#xff09;所示。 分析 下面总结什么样的节…

【RtpSeqNumOnlyRefFinder】webrtc m98: ManageFrameInternal 的帧决策过程分析

Jitterbuffer(FrameBuffer)需要组帧以后GOP内的参考关系 JeffreyLau 大神分析 了组帧原理而参考关系(RtpFrameReferenceFinder)的生成伴随了帧决策 FrameDecisionFrameDecision 影响力 帧的缓存。调用 OnAssembledFrame 传递已经拿到的RtpFrameObject 那么,RtpFrameObject…

【面试专题】设计模式篇①

1.工厂设计模式 工厂设计模式是一种创建型模式&#xff0c;它提供了一种创建对象的接口&#xff0c;但具体创建的对象类型可以在运行时决定。工厂设计模式主要解决的是创建对象的灵活性问题。 工厂设计模式主要包括简单工厂模式、工厂方法模式和抽象工厂模式三种。 简单工厂…