第 103 期 - VueUse useFetch 功能与实现解析
摘要
文章主要介绍了 VueUse 中 useFetch 函数的功能,包括请求发送、响应处理、状态管理、钩子函数、取消请求、超时设置以及各种请求方法和返回内容格式的设置等,逐步展示了 useFetch 函数的实现过程。
一、useFetch 的基本功能介绍
文章开篇提到useFetch通过Fetch API方式发送请求,并具备一些特殊功能,如在触发请求之前拦截请求、在url更改时自动重新获取请求以及使用预定义选项创建自己的请求封装。
二、useFetch 的使用示例
(一)基础引入
示例代码import { useFetch } from '@vueuse/core',const { isFetching, error, data } = useFetch(url)展示了useFetch的基础使用方式。
三、useFetch 的源码解析
(一)简单的 Fetch API 封装
最初的useFetch函数简单封装了fetch,如export function useFetch(url, options) { return fetch(url, options) }。
(二)添加默认请求类型
- 给请求添加默认是
GET的请求,配置对象const config = { method: 'GET' },然后函数变为return fetch(url, { method: config.method,...options })。 - 对于
Fetch获取response body,默认以文本形式获取,在配置对象中添加type: 'text',并在函数中处理response数据。例如:
const data = ref(null);
return {
data,
fetch: fetch(url, { method: config.method,...options }).then(async (response) => {
const responseData = await response[config.type]();
data.value = responseData;
return responseData;
})
};
(三)函数返回值优化
- 为了让函数返回值更符合习惯(直接返回
Promise),给返回值模拟一个then方法。
const promise = fetch(url, { method: config.method,...options }).then(async (response) => {
const responseData = await response[config.type]();
data.value = responseData;
return responseData;
});
return {
data,
then(onFullfilled, onRejected) {
return promise.then(onFullfilled, onRejected);
}
};
- 探讨了返回带有
then方法的对象能否使用await,分析了await后面可接的类型(Promise实例、普通对象、Thenable对象),得出这里返回带有then方法的对象,await可以像处理Promise一样处理。
(四)控制请求发送时机
添加配置项immediate来控制是否马上发送请求,代码如下:
let promise;
const execute = async () => {
return fetch(url, { method: config.method,...options }).then(async (response) => {
const responseData = await response[config.type]();
data.value = responseData;
return responseData;
});
};
if (options.immediate) {
promise = execute();
}
return {
data,
execute,
then(onFullfilled, onRejected) {
return promise? promise.then(onFullfilled, onRejected) : Promise.resolve().then(onFullfilled, onRejected);
}
};
(五)性能优化与更多返回值
- 将
const data = ref(null)换成shallowRef提升性能,并添加response对象到返回值以便特殊处理。 - 对异常信息也进行响应式处理,添加
error到返回值。 - 添加请求的状态响应
isFetching和isFinished,用于判断请求是否正在发送或者已经发送完成。
(六)函数封装与逻辑优化
- 将
isFetching和isFinished的赋值操作封装成一个loading函数。 - 添加配置项
refetch,当为true时,url值改变自动重新发送请求,使用toRef防止refetch和url不是响应式变量。 - 在执行
execute时候用了Promise,如Promise.resolve().then(() => execute()),这在实现设置get、post等方法的时候会用到。
(七)添加钩子函数
- 添加各个阶段的钩子:请求成功、请求失败、请求完成,使用
createEventHook函数来创建钩子。 - 使用发布订阅模式优化钩子函数的实现。
- 补充请求之前的钩子,在
execute函数中通过if (options.beforeFetch)来处理请求之前的操作。
(八)取消请求与超时设置
- 实现取消请求功能,使用
AbortController来中止fetch请求。在useFetch函数中添加相关逻辑,如判断是否支持AbortController,设置canAbort、aborted等变量,实现abort函数。 - 基于取消请求实现设置请求超时时间,添加
timer变量,在execute函数中通过if (options.timeout)设置定时器,超时则调用abort函数。
(九)设置请求方法与返回内容格式
- 添加设置
GET、POST、PUT等方法的函数,通过setMethod函数设置请求方法,在shell对象中添加各种请求方法的调用。 - 设置请求返回内容的格式,通过
setType函数设置不同的返回类型,如json、text、blob等。
