Skip to content

JS 加载失败 重试

js
// https://cdnjs.cloudflare.com/ajax/libs/vue/3.3.4/vue.global.min.js
// https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.min.js
const domains = ['cdn.bootcdn.net1', 'cdnjs.cloudflare.com', 'cdn.jsdelivr.net']
const retryInfo = {}

window.addEventListener(
  'error',
  (event) => {
    console.log('🚀 ~ file: scriptRetryNext ~ window.addEventListener ~ event:', event)

    const tag = event.target
    if (tag.tagName === 'SCRIPT' && !(event instanceof ErrorEvent)) {
      const url = new URL(tag.src)
      if (!retryInfo[url.pathname]) {
        // If it hasn't been retried yet, add retry information
        retryInfo[url.pathname] = {
          times: 0, // Retry times starting from 0
          nextIndex: 0, // Retry domain index starting from 0
        }
      }
      const info = retryInfo[url.pathname]
      if (info.times < domains.length) {
        const script = document.createElement('script')
        script.defer = tag.defer // Copy the defer attribute
        script.async = tag.async // Copy the async attribute
        url.host = domains[info.nextIndex]
        script.src = url.toString()
        script.addEventListener('error', () => {
          // When the script fails to load, continue the next retry
          retryNext(info, url)
        })
        // TODO: IE, Edge existing problem
        // document.write
        document.head.appendChild(script)
        info.times++
        info.nextIndex++
      }
    }
  },
  true
)

function retryNext(info, url) {
  if (info.nextIndex < domains.length) {
    url.host = domains[info.nextIndex]
    const script = document.createElement('script')
    // script.defer = true // Set the defer attribute to ensure asynchronous loading
    // script.async = true // Set the async attribute to ensure asynchronous loading
    script.src = url.toString()
    script.addEventListener('error', () => {
      retryNext(info, url)
    })
    document.head.appendChild(script)
    info.nextIndex++
  }
}