vue-request icon indicating copy to clipboard operation
vue-request copied to clipboard

[v2] 关于 v2 版本 🔥 | About the v2 version

Open John60676 opened this issue 2 years ago • 56 comments

正式版已发布

文档

安装

yarn add vue-request
# or
npm add vue-request

变更列表

  • 使用 vue-demi 兼容 vue2 #38

  • 新增自定义缓存 getCachesetCacheclearCache

  • 开启缓存的情况下,设置了相同 cacheKey 的请求将会被缓存和复用。

  • 新增 runAsyncrefreshAsync,将返回 Promise

  • 新增 definePlugin,可以通过插件来扩展 useRequest 的功能。

  • 节流/防抖模式下可以使用 runAsync 返回正常的 Promise

  • 新增 useRequestProvider hooks,用于注入 options 配置。

  • 新增 refreshDepsAction 选项,用于自定义 refreshDeps 触发后的行为。

  • refreshDepsActionmanual=true 时,也会被 refreshDeps 的改变而触发。

  • 新增 loadingKeep

  • 移除 内部集成请求库,service 不再支持字符或对象。 迁移帮助

  • 移除 formatResult 迁移帮助

  • 移除 queryKey,即移除了并行模式 迁移帮助

  • run 不再返回 Promise 迁移帮助

  • 请求出错时,data 不再会被清空#82

  • 修改 ready 的逻辑 迁移帮助

  • ready 支持传入一个返回布尔值的函数 #166

  • dataerror 改为 shallowRef

  • usePagination 移除了 reload 方法和 reloading。如需要对应的需求,可自行实现。

  • 移除了 RequestConfig 组件 迁移帮助

  • 重构了useLoadMore,具体 API 可查看详情 API 说明

  • cacheKey 支持传入函数: cacheKey: (params?: P) => string

  • refreshDeps 支持传入 一个函数,返回一个值 、是一个 ref 、一个响应式对象 或是由以上类型的值组成的数组 #166

    useRequest(getUser,{
      cacheKey: (params?:P):string => {
        <!-- 初始化时,params 会为 undefined,需要手动判断并返回一个空字符串 -->
        if(params){
          return `user-key-${params[0].name}`
        }
        return ''
      }
    })
    
  • 部分options 支持响应式,如下所示

    type ReactivityOptions = {
      loadingDelay: number | Ref<number>;
      loadingKeep: number | Ref<number>;
      pollingInterval: number | Ref<number>;
      debounceInterval: number | Ref<number>;
      debounceOptions: DebounceOptions | Reactive<DebounceOptions>;
      throttleInterval: number | Ref<number>;
      throttleOptions: ThrottleOptions | Reactive<ThrottleOptions>;
      refreshOnWindowFocus: boolean | Ref<boolean>;
      refocusTimespan: number | Ref<number>;
      errorRetryCount: number | Ref<number>;
      errorRetryInterval: number | Ref<number>;
    };
    

迁移帮助

  1. service 不再支持字符或对象。期望用户可以根据其他第三方请求库进行封装(如 axios),只要提供 Promise 即可
const getUser = userName => {
  return axios.get("api/user", {
    params: {
      name: userName,
    },
  });
};
useRequest(getUser, options);
  1. 移除 formatResult。期望用户自行在 service 中返回最终格式的数据。
const getUser = async () => {
  const results = await axios.get("api/user");
  // 在此处处理最终的数据
  return results.data;
};
  1. 移除 queryKey,即移除了并行模式。期望将每个请求动作和 UI 封装为一个组件,而不是把所有请求都放到父级。

  2. 修改 ready 的逻辑

    • manual=false 时,每次 readyfalse 变为 true 时,都会自动发起请求,会带上参数 options.defaultParams
    • manual=true 时,只要 readyfalse,则无法发起请求。
  3. run 不再返回 Promise。直接用 runAsync 替代原本的 run

  4. 可自行通过 useRequestProvider 封装 。

useLoadMore API

Options

参数 说明 类型
manual 当设置为 true 时,你需要手动触发 loadMore 或者 loadMoreAsync 才会发起请求。默认为 false boolean
ready manual=false 时,每次 readyfalse 变为 true 时,都会自动触发 refresh。当 manual=true 时,只要 readyfalse,则无法发起请求。 Ref<boolean> | () => boolean
refreshDeps 改变后自动触发 refresh,如果设置了 refreshDepsAction 则触发 refreshDepsAction WatchSource<any> | WatchSource<any>[]
refreshDepsAction refreshDeps改变后触发 () => void
debounceInterval 以防抖策略处理请求 number | Ref<number>
debounceOptions 防抖参数 {leading: false, maxWait: undefined, trailing: true}
throttleInterval 以节流策略处理请求 number | Ref<number>
throttleOptions 节流参数 {leading: false, trailing: true}
errorRetryCount 发生错误时的错误重试次数 number | Ref<number>
errorRetryInterval 发生错误时的错误重试间隔时间 number | Ref<number>
isNoMore 判断是否还有更多数据 (data?: R) => boolean
onBefore service 执行前触发 () => void
onAfter service 执行完成时触发 () => void
onSuccess service resolve 时触发 (data: R) => void
onError service reject 时触发 (error: Error) => void

Result

参数 说明 类型
data service 返回的数据,必须包含 list 数组,类型为 { list: any[], ...other } Ref<R>
dataList datalist 数组 Ref<R['list']>
loading 是否正在进行请求 Ref<boolean>
loadingMore 是否正在加载更多 Ref<boolean>
noMore 是否有更多数据,需要配合 options.isNoMore 使用 Ref<boolean>
error service 返回的错误 Error
loadMore 加载更多数据,会自动捕获异常,通过 options.onError 处理 () => void
loadMoreAsync 加载更多数据,返回 Promise,需要自行处理错误 () => Promise<R>
refresh 刷新加载第一页数据,会自动捕获异常,通过 options.onError 处理 () => void
refreshAsync 刷新加载第一页数据,返回 Promise,需要自行处理错误 () => Promise<R>
mutate 直接修改 data 的结果 (arg: (oldData: R) => R) => void | (newData: R) => void
cancel 取消请求 () => void

待办列表

  • [x] 部分 options 支持响应式。 (>= 2.0.0-alpha.3)
  • [x] 重新设计 usePagination。 (>= 2.0.0-alpha.3)
  • [x] 重新设计 useLoadMore。 (>= 2.0.0-beta.2)
  • [x] 支持 taro 等小程序的环境。 (>= 2.0.0-rc.1)

注意

有问题需要反馈的,请开个 issue 讨论

John60676 avatar Mar 24 '22 06:03 John60676

pnpm 安装失败

dmyz avatar Mar 29 '22 07:03 dmyz

@dmyz 已修复

John60676 avatar Mar 29 '22 08:03 John60676

实参类型 function(any): AxiosPromise<any> 不可分配给形参类型 Service<AxiosResponse<any>, []>   类型 function(any): AxiosPromise<any> 不可分配给类型 () => Promise<AxiosResponse<any>> 

axios.create 创建的实例请求类型错误

robin-dongbin avatar Mar 31 '22 09:03 robin-dongbin

@winter-ice 这是你类型写错了吧,贴个示例代码看看

John60676 avatar Apr 01 '22 01:04 John60676

@John60676 我直接用示例代码,IDE(Webstorm)也会警告, 不知道为什么

const getUser = userName => {
  return axios.get('api/user', {
    params: {
      name: userName,
    },
  });
};
const { data, runAsync } = useRequest(getUser)

  await runAsync({ page: index })
image image

robin-dongbin avatar Apr 01 '22 01:04 robin-dongbin

@winter-ice

我特意用了 ws 去测试,也没有重现你的问题 image

John60676 avatar Apr 01 '22 02:04 John60676

@John60676 那应该可能是版本问题了

vue-request 2.0.0-alpha.2 ws EAP 版本,可能是EAP的问题 忽略吧,等之后我再观察看看

robin-dongbin avatar Apr 01 '22 02:04 robin-dongbin

@winter-ice 我换了个eap版本也没法重现,你看看能不能开个issue提供一下更详细的信息

John60676 avatar Apr 01 '22 02:04 John60676

@John60676 没有更详细的信息了,也没有搞什么特殊的配置,用的其他库也没有出现这种情况,如果你那没复现,那就还是等正式版的时候如果还有问题我再研究研究吧。添麻烦了,感谢🙏

robin-dongbin avatar Apr 01 '22 02:04 robin-dongbin

分页请求用runAsync时,不会带defaultParams参数

dmyz avatar Apr 06 '22 17:04 dmyz

@dmyz 这是预期行为,分页请求应当使用内部提供的分页方法 ( changeCurrent, changePageSize, changePagination ),如果需要用到 run 或者 runAsync 请自行管理参数

John60676 avatar Apr 07 '22 01:04 John60676

export { RequestConfig, setGlobalOptions, useLoadMore, usePagination, useRequest }; 可否有打算将 Options 也加入其中允许?便于使用 Options 对其进行二次封装扩展 如:export { RequestConfig, setGlobalOptions, useLoadMore, usePagination, useRequest, Options };

caocos avatar Apr 28 '22 01:04 caocos

@caocaoem 有提供一个 definePlugin 可以进行二次封装,只是我忘了导出而已😅

John60676 avatar Apr 28 '22 01:04 John60676

@caocaoem 有提供一个 可以进行二次封装,只是我忘了导出而已definePluginsweat_smile

确实看到了,希望下一版本能将其导出来,感谢~

caocos avatar Apr 28 '22 01:04 caocos

cacheKey 设置后不起作用,缓存时间内还是访问后端接口

dmyz avatar May 07 '22 12:05 dmyz

@dmyz 如果你要一定时间内不请求接口的,你应该设置一个 staleTime

John60676 avatar May 10 '22 01:05 John60676

@.***

loading 状态返回不正常

dmyz avatar May 10 '22 02:05 dmyz

@dmyz 请单独提issue,并提供重现示例。不要直接说什么什么不行

John60676 avatar May 10 '22 02:05 John60676

提一个现在碰到的很实用的优化建议: 如果接口A开启了cacheKey缓存并且开启了staleTime, 假设接口A的返回时间比较慢(假设10s) 短时间内连续多次请求接口A(第一次的请求还没返回呢,后面的请求又发起了),应该只有第一次的请求进行真正的请求,其余的请求进行等待,当第一个请求完成并写入cache后,后面的请求应用cache的值。

yuntian001 avatar Jun 10 '22 08:06 yuntian001

@yuntian001 2.x 在设置了cacheKey 的情况下,请求也是会进行复用的

John60676 avatar Jun 10 '22 08:06 John60676

@John60676 你看下面的代码 一进入页面会发起三次请求 组件加载一次 两次调用api共三次(因为三次调用时间间隔小cache还没写入成功) 只有在点击按钮后 才会复用请求 不发起真正的请求(因为这时候cahce已经写入成了)

<script setup>
import { useRequest } from 'vue-request';
import axios from 'axios';

const getUser = userName => {
  return axios.get('http://jsonplaceholder.typicode.com/posts');
};

const { data, runAsync } = useRequest(getUser, {
  cacheKey: 'test'
  , staleTime: 60000
});

// ...
let api = async () => {
  let a =await runAsync();
  console.log(a)
};
api();
api();
</script>

<template>
  <button @click="api()">请求</button>
</template>

<style>
</style>

yuntian001 avatar Jun 10 '22 09:06 yuntian001

cahce

确认你测的版本是 v2 哦

@John60676 你看下面的代码 一进入页面会发起三次请求 组件加载一次 两次调用api共三次(因为三次调用时间间隔小cache还没写入成功) 只有在点击按钮后 才会复用请求 不发起真正的请求(因为这时候cahce已经写入成了)

<script setup>
import { useRequest } from 'vue-request';
import axios from 'axios';

const getUser = userName => {
  return axios.get('http://jsonplaceholder.typicode.com/posts');
};

const { data, runAsync } = useRequest(getUser, {
  cacheKey: 'test'
  , staleTime: 60000
});

// ...
let api = async () => {
  let a =await runAsync();
  console.log(a)
};
api();
api();
</script>

<template>
  <button @click="api()">请求</button>
</template>

<style>
</style>

确认你测的版本是 v2 哦

John60676 avatar Jun 10 '22 10:06 John60676

cahce

确认你测的版本是 v2 哦

@John60676 你看下面的代码 一进入页面会发起三次请求 组件加载一次 两次调用api共三次(因为三次调用时间间隔小cache还没写入成功) 只有在点击按钮后 才会复用请求 不发起真正的请求(因为这时候cahce已经写入成了)

<script setup>
import { useRequest } from 'vue-request';
import axios from 'axios';

const getUser = userName => {
  return axios.get('http://jsonplaceholder.typicode.com/posts');
};

const { data, runAsync } = useRequest(getUser, {
  cacheKey: 'test'
  , staleTime: 60000
});

// ...
let api = async () => {
  let a =await runAsync();
  console.log(a)
};
api();
api();
</script>

<template>
  <button @click="api()">请求</button>
</template>

<style>
</style>

确认你测的版本是 v2 哦

肯定是v2啊,你可以随便起个vue项目自测一下啊,再说v1也没有runAsunc啊

yuntian001 avatar Jun 11 '22 09:06 yuntian001

产生这个问题的原因是,发起请求时上一个请求还没完成缓存还没写入。建议第一次请求就记录下,后续请求在拿不到cache时做个事件注册,等第一次请求完成后就触发这个事件event。

yuntian001 avatar Jun 11 '22 09:06 yuntian001

产生这个问题的原因是,发起请求时上一个请求还没完成缓存还没写入。建议第一次请求就记录下,后续请求在拿不到cache时做个事件注册,等第一次请求完成后就触发这个事件event。

https://codesandbox.io/s/sharp-blackwell-88uops

处理逻辑没有问题哦。这里的逻辑是这样的:当缓存还没建立时,确保在同一个组件里同一个请求使用最新的那个相关代码;如果是不同组件,发起同一个请求,则会使用缓存中的请求。

John60676 avatar Jun 13 '22 02:06 John60676

产生这个问题的原因是,发起请求时上一个请求还没完成缓存还没写入。建议第一次请求就记录下,后续请求在拿不到cache时做个事件注册,等第一次请求完成后就触发这个事件event。

https://codesandbox.io/s/sharp-blackwell-88uops

处理逻辑没有问题哦。这里的逻辑是这样的:当缓存还没建立时,确保在同一个组件里同一个请求使用最新的那个相关代码;如果是不同组件,发起同一个请求,则会使用缓存中的请求。

但是同一个组件被父组件引用好几次是很正常的啊,比如父组件需要两个地址选择框,就会声明两个地址选择组件,这两个地址选择组件就会在初始化的时候都会去请求初始化数据。这时候就相当于多次请求了

yuntian001 avatar Jun 13 '22 08:06 yuntian001

https://codesandbox.io/s/sharp-blackwell-88uops

@yuntian001 这个 demo 就是你说的场景呀

John60676 avatar Jun 13 '22 08:06 John60676

https://codesandbox.io/s/sharp-blackwell-88uops

@yuntian001 这个 demo 就是你说的场景呀

你的setup 里没有进行请求啊,只是点击才进行的请求,一般组件在setup里created或者onmounted就会去请求初始化数据

yuntian001 avatar Jun 13 '22 09:06 yuntian001

@yuntian001

manualfalse 或者不设置的情况下,会在挂载时发起请求。文档:https://www.attojs.com/api/#manual

2.x 的文档还没写,但是与 1.x 有区别的地方都在该 issue 开头列出来了,所以可以用 1.x 的文档对照本文先用着

John60676 avatar Jun 13 '22 09:06 John60676

manual

我本地试了组件多次挂载的情况下确实没问题,谢啦

yuntian001 avatar Jun 13 '22 09:06 yuntian001