基于fetchAPI封装newFetch方法,实现请求超时/错误重新发送一次

  • 知识点
    • 阻断请求方法
      1. AbortController 控制器,可以阻断web请求
          // IE不支持
         const controller = new AbortController()
          // AbortController.signal属性获取其关联 AbortSignal对象的引用
         const signal = controller.signal
         controller.abort()
        
      2.兼容ieXMLHttpRequest.abort()
    • Promise.race([])
      • 同时发送多个请求,返回最先请求到的结果
      • 问题: 当我们重传的时候,如果不终止上一次请求。上次请求依然执行
    • 代码
      let newFetch = (url) => {
              // 重传次数控制
              let requestAgain = 0
              // 创建控制器对象
              const controller = new AbortController()
              // AbortController.signal属性获取其关联 AbortSignal对象的引用
              const signal = controller.signal
              //判断是否为IE 该判断不支持IE11 以上
              if (navigator.userAgent.indexOf('MSIE') > -1) {
                  // 如果是ie 不支持-- AbortController--
                  // 也不支持fetch
                  // 此时使用原生xmlHttpRequest
                  // ie5/6和ie6+创建xmlHttpRequest对象有所不同
                  return new Promise((resolve, reject) => {
                      xmlreq(url, 'GET', resolve)
                  }).then((res) => {
                      // console.log('success')
                      // console.log(res)
                  }).catch(err => {
                      // 重新发送请求一次
                      if (requestAgain != 0) return
                      requestAgain++
                      xmlreq(url, 'GET', resolve)
                  })
              } else {
                  // 不是ie
                  return Promise.race([requestPromise(url, signal).then(async (res) => {
                      let result = await res.json()
                      // console.log(result)
                  }).catch((err) => {
                      // 错误时重发
                      // 使用控制器终止请求
                      controller.abort()
                      // 重新发送请求
                      requestPromise(url).then(async (res) => {
                          let result = await res.json()
                          // console.log('请求重发')
                          // console.log(result)
                      })
                  }), new Promise((resolve, reject) => {
                      setTimeout(() => {
                          // 使用控制器终止请求
                          controller.abort()
                          // 重新发送请求一次
                          if (requestAgain != 0) return
                          requestAgain++
                          requestPromise(url).then(async (res) => {
                              let result = await res.json()
                              // console.log('请求重发')
                              // console.log(result)
                          })
                      }, 30000);
                  })])
              }
    
          }
          // 封装fetch 请求
          let requestPromise = (url, signal = {}) => {
              return fetch(url, {
                  signal,
                  headers: {
                      "Content-Type": 'application/json;charset=utf-8;'
                  }
              })
          }
          // 封装xmlHTTPRequest
          let xmlreq = (url, methods = 'GET', resolve) => {
              // 创建xmlHttpRequest 对象
              let xmlHttpReq
              if (window.XMLHttpRequest) {
                  // ie6+
                  xmlHttpReq = new XMLHttpRequest();
    
              } else {
                  // ie5/6
                  xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP")
              }
              // 设置超时时间
              xmlHttpReq.timeout = 30000
              xmlHttpReq.open('GET', url)
              xmlHttpReq.send()
              xmlHttpReq.ontimeout = (event) => {
                  // 终止上一次请求
                  xmlHttpReq.abort()
                  // 重新发送请求
                  xmlHttpReq.send()
              }
              xmlHttpReq.onreadystatechange = function (event) {
                  if (event.target.readyState == 4 && event.target.status == 200) {
                      let resData = JSON.parse(xmlHttpReq.response)
                      resolve(resData)
                  }
              }
          }
          newFetch('http://a.com')
    
    • 个人理解 写的不对的地方希望大家指出,谢谢。

你可能感兴趣的:(基于fetchAPI封装newFetch方法,实现请求超时/错误重新发送一次)