溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript怎么安全的進(jìn)行數(shù)據(jù)獲取

發(fā)布時(shí)間:2023-03-21 14:58:15 來源:億速云 閱讀:113 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“JavaScript怎么安全的進(jìn)行數(shù)據(jù)獲取”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“JavaScript怎么安全的進(jìn)行數(shù)據(jù)獲取”吧!

獲取數(shù)據(jù)的方式

fetch可能是我們在 JavaScript 獲取數(shù)據(jù)最常見的方式。

但是,我們用fetch獲取數(shù)據(jù)的的代碼很有可能存在安全問題:

代碼示例:

const res = await fetch('/user')
const user = await res.json()

上面這段代碼雖然簡單好用,但存在許很多問題。

  • 問題一、缺少“錯(cuò)誤處理”

當(dāng)然你可能會說這個(gè)問題很好解決嘛,給她添加一個(gè)try/catch就好了,遇到錯(cuò)誤就會拋出了嘛!

代碼示例:

try {
  const res = await fetch('/user')
  const user = await res.json()
} catch (err) {
  // 處理錯(cuò)誤的代碼
}

當(dāng)然,這樣可以確實(shí)可以對我們的錯(cuò)誤進(jìn)行處理了。遇到錯(cuò)誤的時(shí)候也會拋出,但是就算這樣寫了還是存在很多的問題,對錯(cuò)誤的覆蓋能力不全面。

  • 問題二:無法識別部分錯(cuò)誤代碼

在這里,我們假設(shè)user實(shí)際上是一個(gè)用戶對象。我們假設(shè)我們得到了響應(yīng)200。

但是fetch不會針對非 200 的狀態(tài)拋出錯(cuò)誤,因此如果你收到了400(錯(cuò)誤請求)、401(未授權(quán))、404(未找到)、500(內(nèi)部服務(wù)器錯(cuò)誤)或各種其他問題都不會進(jìn)行錯(cuò)誤拋出。

那你可能有會說了那我們用個(gè)if進(jìn)行判斷然后對不同的錯(cuò)誤碼進(jìn)行分類處理不就好了!

于是我們就有了下面的代碼

try {
  const res = await fetch('/user')
  if (!res.ok) {
    switch (res.status) {
      case 400: /* 錯(cuò)誤處理 */ break
      case 401: /* 錯(cuò)誤處理 */ break
      case 404: /* 錯(cuò)誤處理 */ break
      case 500: /*錯(cuò)誤處理 */ break
    }
  }
  // User 已經(jīng)是我們最新的數(shù)據(jù)了
  const user = await res.json()
} catch (err) {
  // 錯(cuò)誤處理
}

現(xiàn)在,我們算是基本實(shí)現(xiàn)了fetch對數(shù)據(jù)的安全獲取了. 但是這樣寫是很臃腫且笨重的,因?yàn)槊看味急仨氈貙憣懸淮五e(cuò)誤的處理邏輯,而如果是團(tuán)隊(duì)開發(fā)的話對每個(gè)成員的要求會更高,要求每個(gè)同事都要按照同樣的邏輯來處理請求。而且在可讀性方面,也是很差的,維護(hù)起來很麻煩。

那么我們可不可以換一種更優(yōu)雅的方式來處理我們的邏輯代碼呢?

更優(yōu)雅的方式

我們可以使用throw來處理我們的不同的錯(cuò)誤響,而不是使用switch/case.

try {
  const res = await fetch('/user')
  if (!res.ok) {
    throw new Error('錯(cuò)誤的響應(yīng)')
  }
  const user = await res.json()
} catch (err) {
  // 錯(cuò)誤處理
}

但是我們還剩下最后一個(gè)問題——就是當(dāng)我們需要處理錯(cuò)誤時(shí),我們丟失了很多有用的上下文。我們無法在 catch 塊中訪問,因此查看處理錯(cuò)誤時(shí)我們上并不知道響應(yīng)的狀態(tài)代碼或錯(cuò)誤的詳細(xì)信息。

這會讓我們debug變的很困難,很難去查錯(cuò)。那我們要怎么才能拿到error的上下文呢?

最好的方法可能是創(chuàng)建我們自己的自定義錯(cuò)誤類,并且在錯(cuò)誤類中轉(zhuǎn)發(fā)響應(yīng)的詳細(xì)信息:

代碼:

class ResponseError extends Error {
  constructor(message, res) {
    super(message)
    this.response = res
  }
}
try {
  const res = await fetch('/user')
  if (!res.ok) {
    throw new ResponseError('錯(cuò)誤的響應(yīng)信息(error的上下文信息)', res)
  }
  const user = await res.json()
} catch (err) {
  //我們可以拿到錯(cuò)誤的詳細(xì)信息,也就是error的上下文
  switch (err.response.status) {
    case 400: /* 錯(cuò)誤處理 */ break
    case 401: /* 錯(cuò)誤處理 */ break
    case 404: /* 錯(cuò)誤處理 */ break
    case 500: /* 錯(cuò)誤處理 */ break
  }
}

現(xiàn)在我們保留狀態(tài)代碼等error信息,這樣可以讓我們的用戶了解錯(cuò)誤的原因的也能讓我們更好的處理錯(cuò)誤。

例如,我們可以提醒用戶500我們遇到了問題,并可以讓客戶聯(lián)系我們的進(jìn)行解決。

或者如果狀態(tài)為401,則他們當(dāng)前未授權(quán),可能需要重新登錄等。

封裝類

雖然上面的代碼可以解決我們的所有問題,但是它仍然存在一個(gè)不穩(wěn)定性,就是代碼的健壯性取決于開發(fā)人員的個(gè)人素質(zhì)和能力。我們的的請求安全并不能等到統(tǒng)一的保障。

我們可以對我們代碼進(jìn)行封裝,然后使用時(shí)進(jìn)行導(dǎo)出引用就行了

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('錯(cuò)誤響應(yīng)的信息', res)
  }
  return res
}

然后我們可以按下面的方式去使用它:

try {
  const res = await myFetch('/user')
  const user = await res.json()
} catch (err) {
  // 錯(cuò)誤的處理代碼
}

在我們的封裝代碼中,最好確保有一個(gè)統(tǒng)一的方式來處理錯(cuò)誤。因?yàn)檫@里面包括給用戶的警報(bào)、日志記錄等。

開源的解決方案

當(dāng)然如果我們的水平還沒有達(dá)到可以自己封裝一個(gè)完善的請求類時(shí)我們也可以去網(wǎng)上使用一些別封裝好的請求類,

axios

  • axios是一個(gè)非常流行的 JS 請求數(shù)據(jù)的庫,它已經(jīng)幫我們解決了上面我們探討的幾個(gè)問題。

try {
  const { data } = await axios.get('/user')
} catch (err) {
  // 錯(cuò)誤處理代碼
}

我覺得 Axios 的唯一缺點(diǎn)是包太大,如果我們只是在一個(gè)項(xiàng)目獲取一個(gè)很簡單的數(shù)據(jù)時(shí)使用axios需要引入一個(gè)11kb的包,,反而會使我們的項(xiàng)目變的臃腫。

Redaxios

如果你覺得項(xiàng)目的大小對你更重要是你可以選擇Redaxios

  • Redaxios使用有 Axios 一樣的 API,但不到大小卻不到[1kb]

import axios from 'redaxios'
// use as you would normally

Wretch

還有一個(gè)不錯(cuò)的選項(xiàng)是Wretch,它是 Fetch封裝成的一個(gè)非常小的包,和 Redaxios 一樣。Wretch 的特別之處在于它在很大程度上還原了原生的數(shù)據(jù)請求方法,但是它幫我們封裝了很多的錯(cuò)誤處理代碼。

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 */ })

感謝各位的閱讀,以上就是“JavaScript怎么安全的進(jìn)行數(shù)據(jù)獲取”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對JavaScript怎么安全的進(jìn)行數(shù)據(jù)獲取這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI