fetch实现JWT无感刷新

273 阅读1分钟

fetch实现JWT无感刷新

// token 是否逾期,正在重新请求。。。
const isRefreshing = false

// 存储请求队列
const requests  = []

// 重新设置JWT Token
const getCurrentJwt = async () => {
  try {
    // 得到新的jwt token
    const res = await getBcCurrentJWT()

    B3SStorage.set('bc_jwt_token', res)
    return res
  } catch (error) {
    console.log(error)
  }
}

const refresh = async (path, init) => {
  if (!isRefreshing) {
    isRefreshing = true

    try {
      const token = await getCurrentJwt()

      const reInit = {
        headers: {
          ...init.headers,
          Authorization: `Bearer  ${token}`,
        },
        method: init.method,
        body: init.body,
      }
  
      // 执行加入在requests 队列
      requests.forEach(item => item(token))

      isRefreshing = false
      // 再次执行第一个jwt失败的请求
      return b3Fetch(path, reInit)
    } catch (error) {
        // 清除token
      removeToken()
      router.push('/login')
      isRefreshing = false
    }

    
  } else {
    // 返回未执行 resolve 的 Promise
    return new Promise(resolve => {
      // 用函数形式将 resolve 存入,等待刷新后再执行
      requests.push(token => {
        const reInit = {
          headers: {
            ...init.headers,
            Authorization: `Bearer  ${token}`,
          },
          method: init.method,
          body: init.body,
        }
        resolve(b3Fetch(path, reInit))
      })
    })
  }
}

const b3Fetch = (path, init) => {
  window.fetch.then(res => res.text()).then(async (data) => {
    // token 逾期 执行
    if (data.code === 409) {
      refresh(path, init)
    }
  })
}