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>
  );
};
复制代码


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

目录
相关文章
|
3月前
|
JavaScript 前端开发 API
Vue.js 3.x新纪元:Composition API引领潮流,Options API何去何从?前端开发者必看的抉择指南!
【8月更文挑战第30天】Vue.js 3.x 引入了 Composition API,为开发者提供了更多灵活性和控制力。本文通过示例代码对比 Composition API 与传统 Options API 的差异,帮助理解两者在逻辑复用、代码组织、类型推断及性能优化方面的不同,并指导在不同场景下的选择。Composition API 改善了代码可读性和维护性,尤其在大型项目中优势明显,同时结合 TypeScript 提供更好的类型推断和代码提示,减少错误并提升开发效率。尽管如此,在选择 API 时仍需考虑项目复杂性、团队熟悉度等因素。
51 0
|
6月前
|
JavaScript Java 测试技术
基于springboot+vue.js的中山社区医疗综合服务平台附带文章和源代码设计说明文档ppt
基于springboot+vue.js的中山社区医疗综合服务平台附带文章和源代码设计说明文档ppt
24 0
基于springboot+vue.js的中山社区医疗综合服务平台附带文章和源代码设计说明文档ppt
|
5月前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的果蔬种植销售一体化服务平台附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的果蔬种植销售一体化服务平台附带文章和源代码部署视频讲解等
28 0
|
5月前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的智能实时疫情监管服务平台附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的智能实时疫情监管服务平台附带文章和源代码部署视频讲解等
23 0
|
6月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的智能实时疫情监管服务平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的智能实时疫情监管服务平台的详细设计和实现(源码+lw+部署文档+讲解等)
|
6月前
|
JavaScript Java 测试技术
基于ssm+vue.js的深加工农产品推广服务平台附带文章和源代码设计说明文档ppt
基于ssm+vue.js的深加工农产品推广服务平台附带文章和源代码设计说明文档ppt
26 0
|
JavaScript 前端开发
前端基础 - JQuery实现省级联动
前端基础 - JQuery实现省级联动
50 0
|
索引
【 uniapp - 黑马优购 | 分类界面 】创建cate分支、数据获取、动态渲染
【 uniapp - 黑马优购 | 分类界面 】创建cate分支、数据获取、动态渲染
157 0
|
前端开发 Android开发
vue-cli 项目配置 lib-flexible【阿里手淘移动端自适应解决方案】
vue-cli 项目配置 lib-flexible【阿里手淘移动端自适应解决方案】
vue-cli 项目配置 lib-flexible【阿里手淘移动端自适应解决方案】
|
Web App开发 编解码 前端开发
vue 接入腾讯实时音视频 trtc-js-sdk 的技术难点与解决方案
1.低延迟,如果要满足比较流畅地进行实时互动,那么单向的端到端的迟延大概要在 400 毫秒以下才能保证流畅沟通; 2.流畅性,你也很难想象在视频过程中频繁卡顿会有良好的互动; 3.回声消除,回声的产生是扬声器播放的声音经过环境反射被麦克风重新采集并传输给对方,这样对方就会一直听到自己的回声,整个互动过程会非常难受; 4.国内外互通,随着现在国内同质化产品越来越多,国内的竞争也异常激烈,很多厂商纷纷选择出海,这时就需要做好海内外的互通; 5.海量并发,当然这不仅仅指实时音视频了,基本对于任何一款互联网产品而言都是必须要考虑的难点。
911 0