前言
这篇文章将对
ky
库进行简单的使用并进行一个基本的封装
ky
简介
ky
是一个基于fetch
API封装的请求库,兼容浏览器和node,类似于axios
,但是axios
的实现是在浏览器端是基于XMLHttpRequests
而在node端则是基于原生的http
模块.
目前ky
在github上有13.6k的Star,还是非常火的,不能总拘泥于常用的axios
所以我决定试用一下ky
简单试用
先随便开个Vue项目
安装ky
pnpm i ky
基本使用
<script setup lang="ts">
import ky from 'ky'
async function kyTest() {
const res = await ky.get('http://localhost:3000/todo').json()
console.log(res)
}
</script>
<template>
<button @click="kyTest">
请求测试
</button>
</template>
3000端口开了一个我自己写的后端
这里可以看到请求的data直接被json()
方法取出来了
ts类型
用ts的话此时的res类型是unknown
可以通过传泛型去定义
先定义一个类型
interface TodoType {
code: number
msg: string
data: {
id: string
title: string
isCheck: boolean
time: string
}
}
在原本的请求上修改一下
const res = await ky.get<TodoType>('http://localhost:3000/todo').json()
// 或者
const res = await ky.get('http://localhost:3000/todo').json<TodoType>()
// 或者
const res = await ky<TodoType>('http://localhost:3000/todo', { method: 'GET' }).json()
简单封装
阅读文档可以得知ky
支持类似于axios
的create
方法.并且内置了几个hooks
这里在utils
文件夹中开始封装
新建一个文件夹名为KY
并新建index.ts
// index.ts
import ky from 'ky'
const KY = ky.create({})
export default KY
在项目中请求的地址一般会有一个环境变量
比如开发阶段会经常使用mock
测试和生产都会有单独的地址
所以使用vite的环境变量作为基请求地址
ky
会自动重试,我们需要把它设置为0
import ky from 'ky'
const { VITE_APP_URL } = import.meta.env
const KY = ky.create({
prefixUrl: VITE_APP_URL,
retry: 0,
})
export default KY
需要注意的是封装之后请求不用再以
/
开头并且以/
开头会报错比如prefixUrl为
http://localhost:3000
则请求的时候只需要
await KY<TodoType>('todo', { method: 'GET' }).json()
即可
拦截器/钩子
ky
提供了几种钩子
beforeRequest
请求发起之前调用钩子beforeRetry
重试发起之前调用钩子beforeError
请求抛出HTTPError
之前调用的Hook 可以进行一些错误处理afterResponse
请求响应之后调用的钩子 可以统一处理一下请求响应
使用也很简单
const KY = ky.create({
prefixUrl: VITE_APP_URL,
retry: 0,
hooks: {
beforeRequest: [
(request: KyRequest) => {
console.log(request)
},
],
},
})
但是我不想把方法都写在index里所以新建一个tool.ts
文件
beforeRequest
主要是用来加上token
const beforeRequest: BeforeRequestHook[] = [
(request: KyRequest) => {
// 获取token 这里模拟一下
const token = 'xxxxx'
if (token)
request.headers.set('token', token)
},
]
beforeError
用来处理网络错误
const networkErrMap: { [key: string]: string } = {
400: '错误的请求',
401: '无权访问', // 拒绝访问
403: '拒绝访问',
404: '请求错误,未找到该资源',
405: '请求方法未允许',
408: '请求超时',
500: '服务器端出错',
501: '网络未实现',
502: '网络错误',
503: '服务不可用',
504: '网络超时',
505: 'http版本不支持该请求',
}
const beforeError: BeforeErrorHook[] = [
(error: HTTPError<unknown>) => {
const { status } = error.response
// 可以用组件库的方法提示错误
// 比如 ElMessage ElNotification
console.log(networkErrMap[status] ?? '其他网络错误')
return error
},
]
afterResponse
主要是根据业务状态码进行处理,这里不再赘述了
最后
完整代码奉上
// index.ts
import ky from 'ky'
import { beforeError, beforeRequest } from './tool'
const { VITE_APP_URL } = import.meta.env
const KY = ky.create({
prefixUrl: VITE_APP_URL,
retry: 0,
hooks: {
beforeRequest,
beforeError,
},
})
export default KY
// tool.ts
import type { BeforeErrorHook, BeforeRequestHook, HTTPError, KyRequest } from 'ky'
const networkErrMap: { [key: string]: string } = {
400: '错误的请求',
401: '无权访问', // 拒绝访问
403: '拒绝访问',
404: '请求错误,未找到该资源',
405: '请求方法未允许',
408: '请求超时',
500: '服务器端出错',
501: '网络未实现',
502: '网络错误',
503: '服务不可用',
504: '网络超时',
505: 'http版本不支持该请求',
}
const beforeRequest: BeforeRequestHook[] = [
(request: KyRequest) => {
// 获取token 这里模拟一下
const token = 'xxxxx'
if (token)
request.headers.set('token', token)
},
]
const beforeError: BeforeErrorHook[] = [
(error: HTTPError<unknown>) => {
const { status } = error.response
// 可以用组件库的方法提示错误
// 比如 ElMessage ElNotification
console.log(networkErrMap[status] ?? '其他网络错误')
return error
},
]
export { beforeError, beforeRequest }
以上