點燈坊

失くすものさえない今が強くなるチャンスよ

若 API 讀取錯誤,則重試 N 次讀取

Sam Xiao's Avatar 2023-06-20

實務上可能遇到 API 讀取錯誤,需自行重試 N 次讀取才能成功。

Version

ECMAScript 2017

tryFetch()

async function tryFetch(url, retries = 3, delay = 1000) {
  try {
    let response = await fetch(url)
    return await response.json()
  } catch (error) {
    if (retries > 0) {
      console.error(error)
      console.warn(`Fetch data failed. ${retries} retries left. Retrying in ${delay} ms...`)
      await new Promise(resolve => setTimeout(resolve, delay))
      return await tryFetch(url, retries - 1, delay)
    } else {
      throw new Error('Fetch data failed after retrying.')
    }
  }
}

try {
  let data = await tryFetch('https://jsonplaceholder.typicode.com/todos/1')
  console.log(data)
} catch(e) {
  console.error(e)
}

Line 1

async function tryFetch(url, retries = 3, delay = 1000) {

tryFetch() 提供 3 個參數:

  • url:API 網址,必傳參數
  • retries:重複次數,預設為 3 次
  • delay:每個 API 呼叫的間隔時間,預設間隔 1 秒鐘

Line 2

try {
  let response = await fetch(url)
  return await response.json()
}
  • 使用 fetch() 呼叫 API
  • 若成功則直接回傳 response

Line 5

catch (error) {
  if (retries > 0) {
    console.error(error)
    console.warn(`Fetch data failed. ${retries} retries left. Retrying in ${delay} ms...`)
    await new Promise(resolve => setTimeout(resolve, delay))
    return await tryFetch(url, retries - 1, delay)
  } else {
    throw new Error('Fetch data failed after retrying.')
  }
}
  • 若失敗則使用 setTimeout() 包成 Promise 模擬 sleep()
  • 再次遞迴執行 tryFetch() ,但 retry 次數減 1
  • 若 retry 到 0 則再次拋出 Error 給用戶

Line 17

try {
  let data = await tryFetch('https://jsonplaceholder.typicode.com/todos/1')
  console.log(data)
} catch(e) {
  console.error(e)
}
  • 使用 try catch 呼叫 tryFetch(),若 3 次都失敗則會進入 catch

Conclusion

  • 可將 setTimeout() 包成 Promise 並搭配 await 模擬 sleep()
  • catch 若 retry 到 0 則再次拋出 Error 給用戶