點燈坊

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

若 URL 不存在,則重試 N 次再繼續

Sam Xiao's Avatar 2023-06-20

實務上可能遇到 URL 已經發布,但 URL 尚無法使用,需自行重試 N 次等 URL 存在再繼續。

Version

ECMAScript 2017

tryCheckUrl()

let checkUrl = async url => {
  try {
    let response = await fetch(url, { method: 'HEAD' })
    return response.ok
  } catch (error) {
    return false
  }
}

let tryCheckUrl = async (url, retries = 5, delay = 3000) => {
  let exists = await checkUrl(url)
  let retry = 0

  while (!exists && retry < retries) {
    console.warn(`URL not found, retrying in ${delay/1000} seconds`)
    await new Promise(resolve => setTimeout(resolve, delay))
    exists = await checkUrl(url)
    retry++;
  }

  if (exists) {
    console.warn('URL found. Continuing with the program.')
    return true
  } else {
    console.warn('Retried ' + retries + ' times with no luck. URL not found.')
    return false
  }
}

let result = await tryCheckUrl('https://www.google.com/')
console.log(result)

Line 1

let checkUrl = async url => {
  try {
    let response = await fetch(url, { method: 'HEAD' })
    return response.ok
  } catch (error) {
    return false
  }
}
  • checkUrl():傳入 URL 簡單判斷是否存在
  • 使用 fetch() 判斷是否存在,若存在則回傳 response.ok,也就是 true
  • 使用 fetch() 判斷是否存在,若不存在則發出 exception,此時回傳 false

Line 10

let tryCheckUrl = async (url, retries = 5, delay = 3000) => 
  • tryCheckUrl():傳入 URL 判斷是否存在,並提供 retry 機制:
    • url:傳入判斷 URL,必傳參數
    • retries:重複次數,預設為 5
    • delay:重試間格時間,預設為 3

Line 11

let exists = await checkUrl(url)
let retry = 0
  • 做第一次的 URL 檢查

Line 14

while (!exists && retry < retries) {
  console.warn(`URL not found, retrying in ${delay/1000} seconds`)
  await new Promise(resolve => setTimeout(resolve, delay))
  exists = await checkUrl(url)
  retry++;
}
  • 使用 while() 持續判斷是否存在,若 URL不存在重試次數小於預定重試次數 則不斷重試
  • 由於重試之間有間格時間,將 setTimeout() 也包成 Promise 並加以 await
  • 再次呼叫 checkUrl() 檢查 URL

Line 21

if (exists) {
  console.warn('URL found. Continuing with the program.')
  return true
} else {
  console.warn('Retried ' + retries + ' times with no luck. URL not found.')
  return false
}
  • 若經過重試之後 URL 存在則回傳 true,否則回傳 false

Line 30

let result = await tryCheckUrl('https://www.google.com/')
console.log(result)
  • 呼叫 tryCheckUrl() 重試 N 次檢查 URL 是否存在

Conclusion

  • 可直接使用 fetch() 判斷 URL 是否存在
  • 可將 setTimeout() 包成 Promise 並搭配 await 模擬 sleep()
  • 直到 tryCheckUrl() 回傳 true 才繼續執行,可避免後續程式因為 URL 不存在而執行錯誤