读取数据的形式
fetch
很有可能是在 JavaScript 读取数据比较常见的方法。
可是,我们用fetch
读取数据的编码极有可能存有安全隐患:
编码实例:
const res = await fetch('/user')
const user = await res.json()
以上这一段编码看似简单实用,但也存在许许多问题。
- 问题一、缺乏“异常处理”
当然你可能说这种情况非常好处理嘛,给他添加一个try/catch
就行了,碰到不正确便会提出了嘛!
编码实例:
try {
const res = await fetch('/user')
const user = await res.json()
} catch (err) {
// 处理错误的代码
}
自然,这可以确实能对于我们的不正确开展解决了。碰到不正确的时候会抛出去,可是即使这样写依旧存在很多的问题,对不正确的覆盖能力不完善。
- 难题二:识别不了一部分错误码
在这儿,大家假定user
实际上是一个客户目标。大家假定大家获得了回应200
。
可是fetch
不容易对于非 200 状态抛出去不正确,因而假如你收到400
(不正确要求)、401
(未经授权)、404
(未找到)、500
(内部结构服务器错误)或各种各样任何问题也不会开展不正确抛出去。
那么你很有可能有会讲了那么我们用个if作出判断随后针对不同的错误代码开展分类处置不就行了!
于是也就有了下边的代码
try {
const res = await fetch('/user')
if (!res.ok) {
switch (res.status) {
case 400: /* 异常处理 */ break
case 401: /* 异常处理 */ break
case 404: /* 异常处理 */ break
case 500: /*异常处理 */ break
}
}
// User 已是大家最新数据信息了
const user = await res.json()
} catch (err) {
// 异常处理
}
如今,大家算得上基本完成了fetch
对业务的安全性获得了.可是这么写是非常松垮且笨重,每次都必须要重新写过写一次不正确的解决逻辑性,但如果是精英团队开发设计得话对所有成员的需求更高一些,规定每一个同事都严格按照一样的思路来处理要求。并且在易读性层面,都是比较差的,维护保养下去太麻烦了。
那样我们可不可以换一种更雅致的方式去解决我们自己的逻辑代码呢?
更典雅的方法
我们可以使用throw
来处理我们自己的不一样错误响,而非应用switch/case
.
try {
const res = await fetch('/user')
if (!res.ok) {
throw new Error('不正确的回应')
}
const user = await res.json()
} catch (err) {
// 异常处理
}
但我们还剩最后一个问题——便是在我们必须处理错误时,大家丢了许多有价值的前后文。我们不能在 catch 块中浏览,因而查询处理错误的时候我们上并不了解回应的状态代码或不正确的详细资料。
这能让我们debug变的很艰难,很难检错。那么我们该怎么才可以获得error的前后文呢?
最好的办法有可能是建立我们自己自定不正确类,而且在不正确类中分享回应的详细资料:
编码:
class ResponseError extends Error {
constructor(message, res) {
super(message)
this.response = res
}
}
try {
const res = await fetch('/user')
if (!res.ok) {
throw new ResponseError('不正确的回应信息内容(error的上下文信息)', res)
}
const user = await res.json()
} catch (err) {
//大家能够拿到不正确的详细资料,其实就是error的前后文
switch (err.response.status) {
case 400: /* 异常处理 */ break
case 401: /* 异常处理 */ break
case 404: /* 异常处理 */ break
case 500: /* 异常处理 */ break
}
}
如今我们保存状态代码等error信息内容,这样才能让我们自己的客户掌握不正确的缘故的都能够让我们更加好的处理错误。
比如,我们能提醒用户500
大家碰见了难题,并能让客户沟通我们自己的开展处理。
或是假如状态为401
,则她们现阶段未经授权,可能还需要重登等。
封装形式类
尽管上边的代码能解决我们自己的各种问题,但它依然存在一个多变性,便是代码的可扩展性在于开发者本人的素质能力。我们自己的请求安全性根本无法直到统一的保证。
我们能对咱们编码开展封装形式,随后使用中开展导出来引入就可以了
class ResponseError extends Error {
constructor(message, res) {
this.response = res
}
}
export async function myFetch(...options) {
const res = await fetch(...options)
if (!res.ok) {
throw new ResponseError('不正确回应的信息', res)
}
return res
}
最后我们能够按下面的方式来使用这些:
try {
const res = await myFetch('/user')
const user = await res.json()
} catch (err) {
// 不正确的解决编码
}
在大家的封装形式编码中,最好是保证有一个统一的方式去处理错误。由于这里边包含给大家的警报器、日志信息等。
开源系统解决方案
自然假如我们水准还没有达到能自己封装形式一个健全请求类时我们还可以去网上使用一些别封装形式好一点的要求类,
axios
- axios是一个比较流行的 JS 请求数据的库,已经帮助我们克服了上边大家讨论的一些问题。
try {
const { data } = await axios.get('/user')
} catch (err) {
// 异常处理编码
}
我认为 Axios 的唯一主要缺点包很大,假如我们只不过是在一个项目获得一个特别简单的数据时应用axios
必须引进一个11kb单肩包,,反倒会让我们的新项目变得松垮。
Redaxios
如果感到新项目大小对自己的更为重要是也可以选择Redaxios
- Redaxios应用有 Axios 一样的 API,但不上尺寸却不上[1kb]
import axios from 'redaxios'
// use as you would normally
Wretch
还有一个非常好这个选项是Wretch,这是 Fetch封装形式而成一个比较小的包,和 Redaxios 一样。Wretch 的独到之处在于它在一定程度上再现了原生的数据请求方式,但它帮助我们封装形式了不少的异常处理编码。
const user = await wretch("/user")
.get()
// Handle error cases in a more human-readable way
.notFound(error => { /* ... */ })
.unauthorized(error => { /* ... */ })
.error(418, error => { /* ... */ })
.res(response => /* ... */)
.catch(error => { /* uncaught errors */ })
文中已经参与「」