设计一个vue3的请求实体工厂

描述

PS: 这里的方法是基于Vue的class写法的,对于setup写法不适用。

主要功能是创建一个具备一个请求完整封装的实例,可以便捷的请求,取消请求,获取数据和请求状态等功能

下面是通过typescript和Vue实现,结合typescript的声明,这个generateRequest方法才会得到升华

实现

实现分下面3个部分

1.构建一个基础请求方法

2.创建具体请求的方法

3.generateRequest对请求的封装

构建一个基础请求方法

这里没啥说的,直接上axios做一个简单的封装

request.ts

import axios from 'axios'
const option = {...}
export request = axios.create(option)

创建具体请求的方法

下面是对请求的声明文件

xxx.d.ts

// 对请求返回的请求体声明
export class Result<T0 = any> {
/** code */
code?:number; /** data */
data?:T0; /** error_code */
error_code?:string; /** error_message */
error_message?:string; /** success */
success?:boolean;
}
// 文章接口返回data声明
export interface ArticleData {
id:number;
title:string;
cover_url:string;
content:string;
read_count:string;
abstract:string;
time:number;
}

下面是请求的定义

api.ts

import { request } from './request'
import { AxiosRequestConfig } from 'axios'
import { Result, ArticleData } from './xxx'
/** 获取文章 */
export const getArticle = (id:number, config?:AxiosRequestConfig) => request.get<Result<ArticleData>>(`/api/article?id=${id}`)

generateRequest对请求的封装

这里主要用到的知识点有:

1.由映射类型进行推断(对参数进行拆包)

2.对上下文的理解

3.vue数据响应式机制

下面是一个基础实现,还可以继续封装对业务场景有用的方法或属性

功能

  • 具备响应式属性:data(返回的数据)loading、isError、params(请求的参数)
  • 可以传入数据处理的方法format
  • 设置data初始值initData
  • 取消请求的cancel方法
  • 发起请求的run方法

utils.ts

import axios, { AxiosPromise, AxiosRequestConfig } from 'axios';
interface GenerateRequestHook<T, K> {
data:T | undefined;
run:(params?:K) => AxiosPromise<T>;
loading:boolean;
isError:boolean;
uid:number;
cancel:((msg?:string) => void);
params:K | undefined;
}
interface Config<L> {
config?:AxiosRequestConfig;
format?:(data:any) => any;
initData?:L;
}
let _uid = 0;
/**
* @description 返回请求的封装实体的request,仅可以在class写法的组建内使用
* @template T
* @template K
* @param {(params?:K, config?:AxiosRequestConfig) => AxiosPromise<T>} reqFunc
* @param {K} [params]
* @param {Config<T>} [config]
* @returns {GenerateRequestHook<T>}
*/
export const generateRequest = <T, K>(reqFunc:(params?:K, config?:AxiosRequestConfig) => AxiosPromise<T>, params?:K, config?:Config<T>):GenerateRequestHook<T, K> => {
const uid = _uid++;
const source = axios.CancelToken.source();
return {
run: async function(_params?:K) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self:GenerateRequestHook<T, K> = this;
if (!self || uid !== self.uid) {
throw Error('[generateRequest] The context exception');
}
try {
self.isError = false;
self.loading = true;
if (_params) {
self.params = _params;
}
const res = await reqFunc(_params || params, {
cancelToken: source.token,
...config?.config,
});
// 格式化返回数据
if (config?.format) {
config.format(res.data);
}
self.data = res.data;
return res;
} catch (error) {
self.data = config?.initData;
self.isError = true;
return Promise.reject(error);
} finally {
self.loading = false;
}
},
data: config?.initData,
loading: false,
isError: false,
uid,
cancel: source.cancel,
params,
};
};

使用demo

<template>
<div class="article_info">
</div>
</template>
<script lang="ts">
import { Vue, Options } from 'vue-property-decorator';
import { generateRequest } from './utils';
import { getArticle } from './api'; @Options({})
export default class extends Vue {
articleReq = generateRequest(getArticle)
created() {
this.articleReq.run(1).then((res) => {
document.title = this.title;
}).catch((err) => {
console.error(err.message);
});
}
}
</script>

上面的this.articleReq会包含的属性,我们可以直接使用loading、data、isError,而且这些属性都是具备响应式的,而且data属性是根据传入getArticle推断出数据类型,十分方便。可以通过cancel方法取消请求,run可以发起请求。

上面我的run方法内有这么一段判断,因为run方法内部是用了this来进行数据更新,让属性具备响应式。不过相对的限制就是不能修改this.articleReq.run调用时的上下文。这样会导致获取属性异常。不过这个限制基本没什么影响,好处是大于坏处的。所以我给每个请求分配一个uid,用于判断请求run方法的上下文是否一致。

if (!self || uid !== self.uid) {
throw Error('[generateRequest] The context exception');
}

结语

上面generateRequest创建了一个具备响应式的请求实例,实现了从请求参数、请求数据都具备声明,且可以直接在组件内使用具备响应式的属性。目前来说还是挺方便的。

设计vue3的请求实体工厂的更多相关文章

  1. [NewLife.XCode]实体工厂(拦截处理实体操作)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  2. IIS7 https 发生413错误 未显示页面,因为请求实体过大

    参考文档:     http://msdn.microsoft.com/zh-cn/library/cc737382(v=ws.10).aspx http://www.java123.net/v/12 ...

  3. ASP.NET MVC上传文件 未显示页面,因为请求实体过大。解方案

    在Dropzone中设置   maxFilesize: 350, //MB 但上传的文件没有到最大限定350MB,就报出来 未显示页面,因为请求实体过大的错误 Web.config中设置  maxAl ...

  4. DDD 领域驱动设计-两个实体的碰撞火花

    上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...

  5. DDD领域驱动设计之聚合、实体、值对象

    关于具体需求,请看前面的博文:DDD领域驱动设计实践篇之如何提取模型,下面是具体的实体.聚合.值对象的代码,不想多说什么是实体.聚合等概念,相信理论的东西大家已经知晓了.本人对DDD表示好奇,没有在真 ...

  6. HTTP API 设计指南(请求部分)

    为了保证持续和及时的更新,强烈推荐在我的Github上关注该项目,欢迎各位star/fork或者帮助翻译 前言 这篇指南介绍描述了 HTTP+JSON API 的一种设计模式,最初摘录整理自 Hero ...

  7. DDD:使用EntityFramework的话,如果只为聚合根设计仓储,其它实体如何处理?

    背景 DDD中只有聚合根可以有仓储,仓储负责整个聚合持久化的相关生命周期,在不使用工作单元或POCO的情况下,我们可以让Order内部直接调用DAL操作OrderItem.我们也可以让Order跟踪所 ...

  8. Ext.ux.UploadDialog上传大文件 HTTP 错误 413.1 - Request Entity Too Large Web 服务器拒绝为请求提供服务,因为该请求实体过大。Web 服务器无法为请求提供服务,因为它正尝试与客户证书进行协商,但请求实体过大。

    问题描述 问题:HTTP 错误 404.13 - Not Found 请求筛选模块被配置为拒绝超过请求内容长度的请求. 原因:Web 服务器上的请求筛选被配置为拒绝该请求,因为内容长度超过配置的值(I ...

  9. Photon Server 实现注册与登录(三) --- 前端UI设计和发起请求

    一.打开之前的测试项目.先将服务端代码编译一下,在 bin/Debug/目录下会发现有一个Common.dill.我们相应导入到前端使用.直接拖拽到相应地方 UI相应布局属于前端操作,这里就不做介绍了 ...

随机推荐

  1. 经济学,金融学:资产证券化 ABS

    经济学,金融学:资产证券化 ABS ABS 资产支持证券 蚂蚁金服如何把30亿变成3000亿?资产证券化 前几天,花呗借呗的东家蚂蚁集团在上市前夕被监管部门叫停,因为这则新闻广大网民都听说了一个概念: ...

  2. 算法的时间复杂度 & 性能对比

    算法的时间复杂度 & 性能对比 累加算法性能对比 // js 累加算法性能对比测试 const n = 10**6; (() => { console.time(`for`); let ...

  3. nasm astrcmp函数 x86

    xxx.asm: %define p1 ebp+8 %define p2 ebp+12 %define p3 ebp+16 section .text global dllmain export as ...

  4. html2Canvas to Images

    <script> $(function () { var content = document.getElementById("shareImages"); conte ...

  5. C++算法代码——奖学金

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1098 题目描述 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学 ...

  6. fixed实现遮罩层,小程序

    css /** 分享微信,分享朋友圈 **/ .goods_share_mask { background-color: rgba(0, 0, 0, 0.3); position: fixed; to ...

  7. 权限管理整合springsecurity代码执行过程

    (1)输入用户名密码. (2)进入认证过滤器中,执行attemptAuthentication方法, 通过该方法获取输入的用户名和密码. (3)执行实现了UserDetailsService接口的类中 ...

  8. 如何把数据放到C#的心里之 DB2实例

    平时偶尔因为工作需要得自己写一些小工具去操作数据库,因为只是需要实现一些小的功能,也不涉及多类型的数据库,也许就是一次性的使用.所以此时那些大而全的数据库操作框架,也就不再那么适合我了.而本篇博文主要 ...

  9. Spirng 循环依赖报错:Requested bean is currently in creation: Is there an unresolvable circular reference?

    1:前言 最近在项目中遇到了一次循环依赖报错的问题,虽然解决的很快,但是有些不明白的地方,特此记录. 在此我把 bean 的结构和 注入方式单独拎出来进行演示 1.1:报错提示 1.2:错误日志 Ex ...

  10. Python3+PYQT5 实现并打包exe小工具(2)

    前言:前篇已经通过python代码实现了逻辑,传送门:https://www.cnblogs.com/jc-home/p/14447850.html 现在后篇记录的是打包成exe的方式给项目其他同事使 ...