鉴于Fetch的二次封装

232 阅读1分钟

前言

客户端服务器端通信方式ajax (ajax JQ的类库 /axios类库) /jsonp / fetch

fetch是Es6新提供的API:基于不同于​XMLHttpRequest的方式,基于客户端和服务器端的数据通信,而且本身是基于promise管理请求结果的(发送请求返回promise实例)

赶快学习起来吧!上代码~

import qs from 'qs'; //这里不详细说qs的使用方法,可以去https://juejin.cn/post/6973835825368793125进行参考'
import {getToken} from './ayth_login';//这是自己封装获取token方法,便于下方代码使用;

import {useCallback} from 'react'; //使用useCallback进行代码的优化;

//首先规定一下类型
interface IConfig extends RequestInit {
    token?:string | null
    data?:Record<string,unknown>
}

const baseURL = proccess.env.REACT_APP_BASE_URL; //这是是取决于哪种环境方式;

let controller = AbortControllter  //这是为了取消上一次请求;

const Http = (url:string,{token,data,...customConfig}:IConfig) => {
    //它会首先判断是否有请求,如果有那么就会取消
    if(controller){
        //使用的是abort
        controller.abort();
    }
    controller = new AbortControllter();
    //在进行配置参数进行二次封装
    const config = {
        method : customConfig.method,
        headers : {
            'content-Type' : 'application/json; charset=utf-8',
             Accept: 'application/json',
        },
        signal:controller.signal, //为了对每次请求进行标记
        ...customConfig,
    }
    
    //对GET/POST请求进行了封装
    if(config.method?.toLocaleUpperCase() === 'GET'){
        url += `?${qs.stringify(data)}`
    }else{
        config.body = JSON.stringify(data)
    }
    //返回接口的promise
    return window.fetch(`${baseURL}${url}`,config).then((response)=>{
        //判断是否有权限
        if(response.status === 401){
            return Promise.reject('权限不足!')
        }
        //请求成功
        if(response.status === 200 && response.ok){
            return response.json()
        }
    }).catch((err)=>{
        console.log(err)
    })
}

//请求超时进行处理
export const httpWithTimeout = (...[url,config]:Parameters<typeof Http>) =>{
    const timeoutPromise = (timeout:number) =>{
           return new Promise((resolve)=>{
               setTimeout(()=>{
                   resolve(new Promise('请求超时',{status:504,statusText:'timeout'}))
               },timeout)
           })
    }
    return Promise.race([timeoutPromise(2000), Http(url, config)])
}

//  获取token,使用useCallback防止重新渲染
export const useHttp = () => {
  const token = getToken()
  return useCallback(
    (...[url, config]: Parameters<typeof Http>) => {
      return httpWithTimeout(url, { ...config, token })
    },
    [token],
  )
}
有不正确的地方,希望大家多多指点!