014 Umi 中的 fetch 与 ahooks useRequest 的梦幻联动

简介: 014 Umi 中的 fetch 与 ahooks useRequest 的梦幻联动

image.png



request 请求数据

Umi@4 中使用 axios 代替了 fetch,有一些使用上的差异,这节课我们提到的是 Umi 中的 fetch 方案


前面我们花了大量的篇幅介绍项目中的数据流方案,其实他们是作为数据消费部分存在的。但是我们并没有真正的发起数据请求,在这里我们将详细的介绍在 umi 中如何规范的发起数据请求,即如何将数据传入我们之前介绍的数据流方案中。


在很多其他项目中,我们都会单独维护一个 http 请求的工具类,它一般会在你的 utils 文件夹中,但是通过多个项目的代码比对,我们发现这个工具类有至少80%的代码是重复的,且不同人员的维护上也比较随意,代码维护上是比较乱的。因此我们将 request 请求内置到框架中。


import { request } from 'umi';
const data = await request('/api/hello', {
  method: 'get',
});
复制代码


直接使用,对服务端的返回数据模型,会有一些约定

如果你的服务端返回数据格式不同,会在后面的配置中提到如何处理这种情况。

interface ErrorInfoStructure {
  success: boolean; // if request is success
  data?: any; // response data
  ...
}
复制代码


一般我们对服务端发起请求,最常见的会涉及到,统一的请求url、统一的head、默认的请求方式(默认 get或者默认post)等。

这些内容,我们都在运行时配置中提供了修改方式。


运行时配置顾名思义就是在项目运行时会根据一些条件或者时机来修改配置,常常用于某些需要动态配置的情况。在前面讲解 umi 中的配置时我们已经提过运行时配置。记住运行时配置只有一个地方 src/app.ts。某些功能会用到它。你需要按约定导出对象,不能导出不存在的对象。这些对象由你所使用的插件定义,包括内置插件和外部引用插件。


export const request = {
  prefix: '',
  method: 'get',
  errorConfig: {
    adaptor: (resData) => {
      return {
        ...resData,
        success: resData.ok,
        errorMessage: resData.message,
      };
    },
  },
};
复制代码

在运行时配置中导出 request 是我们的请求功能要求的。



request 配置

参数 说明 类型 可选值 默认值
method 请求方式 string get , post , put ... get
params url 请求参数 object 或 URLSearchParams 对象 -- --
data 提交的数据 any -- --
headers fetch 原有参数 object -- {}
timeout 超时时长, 默认毫秒, 写操作慎用 number -- --
prefix 前缀, 一般用于覆盖统一设置的 prefix string -- --
suffix 后缀, 比如某些场景 api 需要统一加 .json string -- --
credentials fetch 请求包含 cookies 信息 string -- credentials: 'same-origin'
useCache 是否使用缓存(仅支持浏览器客户端) boolean -- false
validateCache 缓存策略函数 (url, options) => boolean -- 默认 get 请求做缓存
ttl 缓存时长, 0 为不过期 number -- 60000
maxCache 最大缓存数 number -- 无限
requestType post 请求时数据类型 string json , form json
parseResponse 是否对 response 做处理简化 boolean -- true
charset 字符集 string utf8 , gbk utf8
responseType 如何解析返回的数据 string json , text , blob , formData ... json , text
throwErrIfParseFail 当 responseType 为 'json', 对请求结果做 JSON.parse 出错时是否抛出异常 boolean -- false
getResponse 是否获取源 response, 返回结果将包裹一层 boolean -- fasle
errorHandler 异常处理, 或者覆盖统一的异常处理 function(error) --
cancelToken 取消请求的 Token CancelToken.token -- --

fetch 原其他参数有效, 详见fetch 文档


上面列出的是 request 支持的所有配置,看起来有些复杂,但是我们在实际使用中最经常修改的,其实只有 prefix,当你需要切换请求前缀时,会比较频繁的修改它。其他的数据应该是在首次接口连调的时候,和服务端约定好的配置。



修改请求数据-加密或过滤

一般我们还有有一个常用的需求,对我们发出的数据进行安全性的数据加密。或者仅针对某个接口对数据进行过滤。


这时候就能用到我们的中间件功能了。这个在 express 项目中是很容易理解的概念。

const middleware = async (ctx, next) => {
  // 这里是对请求数据的操作,比如加密或者过滤数据,我们可以在这里操作
  // url 请求不包含 ‘abc’ 时,就做某些操作
  if (!ctx.req.url.includes('abc')) {
  }
  await next();
  // next 执行之后,这部分我们一般是对请求结果做操作,比如统一的错误码处理,或者token失效这些,都可以在这里处理
  // 以下代码只是模拟,正式的写法要根据服务端的约定
  if (ctx.res.errors) {
    const {
      errorCode,
      fieldPath,
      message,
      value } = ctx.res.errors[0];
    if (errorCode === '0000') {
      gotoLogin(message);
    } else {
      Toast.fail(`${message}` || '请求异常请稍后重试', 1);
    }
  }
};
export const request = {
  prefix: '', // 统一的请求头
  middlewares: [middleware],
  errorHandler: (error: ResponseError) => {
    // 集中处理错误
    console.log(error);
  },
};
复制代码



ahooks useRequest

理解了上面的概念,那么在我们之前提到的数据流中,应该在什么时机发起请求呢? 一般我们会在 useEffect 中,请求服务端接口,但是为了更加简洁的使用 request,我们引入了 ahooks 中的 useRequest。 这里我们只介绍两种最常见的用法


默认用法

默认用法最好理解,常常用来加载页面的初始化数据。比如列表的首屏展示。

import { useRequest } from 'umi';
import Mock from 'mockjs';
import React from 'react';
function getUsername(): Promise<string> {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(Mock.mock('@name'));
    }, 1000);
  });
}
export default () => {
  const { data, error, loading } = useRequest(getUsername);
  if (error) {
    return <div>failed to load</div>;
  }
  if (loading) {
    return <div>loading...</div>;
  }
  return <div>Username: {data}</div>;
};
复制代码


值得注意的是,上面的代码看起来像是同步执行的,但其实 react 的 hooks 都是异步的,简单理解就是,数据修改时都会导致页面重绘,所以当你的自定义 hooks 很多的时候,可能你的页面会渲染好几次。


手动触发

如果设置了 options.manual = true,则 useRequest 不会默认执行,可以在合适的时候通过 run 来触发执行。比如常见的搜索查询,我们会在输入完条件之后,点击查询按钮才会调用服务端接口。


import { message } from 'antd';
import React, { useState } from 'react';
import { useRequest } from 'umi';
function changeUsername(username: string): Promise<{ success: boolean }> {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ success: true });
    }, 1000);
  });
}
export default () => {
  const [state, setState] = useState('');
  const { loading, run } = useRequest(changeUsername, {
    manual: true,
    onSuccess: (result, params) => {
      if (result.success) {
        setState('');
        message.success(`The username was changed to "${params[0]}" !`);
      }
    },
  });
  return (
    <div>
      <input
        onChange={(e) => setState(e.target.value)}
        value={state}
        placeholder="Please enter username"
        style={{ width: 240, marginRight: 16 }}
      />
      <button disabled={loading} type="button" onClick={() => run(state)}>
        {loading ? 'Loading' : 'Edit'}
      </button>
    </div>
  );
};
复制代码


感谢阅读,这个文章仅仅作为这个概念的讲解,实战在后续课程中,因此这节课没有源码归档。你不需要修改任何的文件。

目录
相关文章
|
前端开发 JavaScript
[项目篇]vue3+ts 移动端和pc端双端实现瀑布流 - 第六天
[项目篇]vue3+ts 移动端和pc端双端实现瀑布流 - 第六天
|
6月前
|
JavaScript 前端开发 开发者
哇塞!Vue.js 与 Web Components 携手,掀起前端组件复用风暴,震撼你的开发世界!
【8月更文挑战第30天】这段内容介绍了Vue.js和Web Components在前端开发中的优势及二者结合的可能性。Vue.js提供高效简洁的组件化开发,单个组件包含模板、脚本和样式,方便构建复杂用户界面。Web Components作为新兴技术标准,利用自定义元素、Shadow DOM等技术创建封装性强的自定义HTML元素,实现跨框架复用。结合二者,不仅增强了Web Components的逻辑和交互功能,还实现了Vue.js组件在不同框架中的复用,提高了开发效率和可维护性。未来前端开发中,这种结合将大有可为。
211 0
|
4月前
|
JavaScript
vue尚品汇商城项目-day03【18.合并params和query参数(Header组件+TypeNav组件)】
vue尚品汇商城项目-day03【18.合并params和query参数(Header组件+TypeNav组件)】
33 0
|
4月前
|
JavaScript
vue尚品汇商城项目-day03【16.开发Search组件模块中的TypeNav商品分类菜单(过渡动画效果)+17.(优化)针对三级菜单联动进行优化,优化方向为减少查询】
vue尚品汇商城项目-day03【16.开发Search组件模块中的TypeNav商品分类菜单(过渡动画效果)+17.(优化)针对三级菜单联动进行优化,优化方向为减少查询】
49 0
|
6月前
|
JavaScript 前端开发 UED
【绝技大公开】Vue.js高手教你如何从零到英雄,构建梦幻电商平台前端!
【8月更文挑战第30天】本文通过对比传统网页开发方式,介绍了使用Vue.js及其生态构建电商平台前端的方法。从初始化项目到配置路由、状态管理,再到实现首页、商品列表与详情页,每个环节都提供了具体代码示例,展示了Vue.js在提升开发效率与应用可维护性方面的优势。适合希望了解现代前端技术栈的开发者阅读。通过本教程,读者可以学习到如何利用Vue Router、Vuex等工具搭建完整的Web应用。
71 0
|
前端开发 JavaScript
【React工作记录八十】 一步步教你用taro封装一个公司库的下拉组件
【React工作记录八十】 一步步教你用taro封装一个公司库的下拉组件
121 0
|
JavaScript 定位技术
vue使用高德地图web端JSAPI 路线规划、搜索提示教程
vue使用高德地图web端JSAPI 路线规划、搜索提示教程
|
数据可视化 JavaScript 定位技术
领导都喜欢看--基于Vue的数据可视化之集成地图聚合功能
领导都喜欢看--基于Vue的数据可视化之集成地图聚合功能
|
缓存 JavaScript 安全
Nuxt3正式发布!5个纬度全方位感受Nuxt3的魅力!
引子 大家好,我 HoMeTown,在Nuxt3公测版过去的一年里,RC版中进行了各种性能改进与功能新增,11月16日,Nuxt3终于迎来了第一个稳定版本3.0的正式发布!🎉
2730 0
|
开发工具 git
【Vue3.0移动端项目--旅游网】-- 城市页面搭建
【Vue3.0移动端项目--旅游网】-- 城市页面搭建
225 0
【Vue3.0移动端项目--旅游网】-- 城市页面搭建