使用fetch封装get与post方法

网上看了一些对fetch的封装,有点看不伶清。如在request中配置timeout与responseType字段等,在文档上找根本找不到。于是自己封装个简单版的fetch,方便拿到项目中改造一下就可以使用。

注意点

  1. 使用fetch时会产生跨域问题,需服务端配置跨域响应头;
  2. fetch中没有接口请求超时的配置,需自己处理,可以使用AbortController控制器;

直接封装

/**
 * @param use 封装的使用场景
 * 1. 本次fetch封装是经过nodeJs的koa框架启动的node服务验证的,对于java启动的服务还需自行验证修改
 * 2. 验证通过了普通的get/psot、表单上传、上传文件,下载文件等
 * @param koa
 * 1. 使用koa搭建服务端时,为了搭配fetch使用要配置跨域,建议使用koa2-cors开源库
 * @param fetch
 * 1. 选择使用fetch是因为是浏览器原生支持的方法,不需引入其它依赖。同时使用fecth会遇到跨域问题,需服务端配置请求响应头
 * 2. 本次封装暴露出了get与post两个方法
 * @param get post
 * 1. 形参主要有 路径path(接口的url):必传,data参数(object):选传,options配置参数(object):选传
 * 2. options参数中可以传入fecth的headers配置等,也有一个默认type属性,默认值为'json',主要处理headers中的'Content-Type'属性值
 * 3. type值有 'json' 'text' 'file' 'blob' 'arrayBuffer'等
 * @param type
 * 1. 加入type值是为了处理'Content-Type'与body取值的问题
 * 2. body取值:在type值为'json'、'text'、'blob'时,需要进行JSON.stringify()转换;在值为'file'时,无需进行转换
 * 3. 'Content-Type'取值:在type值为'json'、'text'、'blob'时,需要配置 headers["Content-Type"] = "application/json";在值为'file'时,无需进行配置,配置了反而有问题,浏览器会自行添加配置
 * @param response
 * 1. 在type值为'json'、'file'时,response.json();值为'text'时,response.text();值为'blob'时,response.blob()
 */

// 基础配置
const baseURL = "http://192.168.0.106:8002";

// 接口报错统一提示
function errorCallBack(message) {
  console.log(`${message || "接口传参错误"}`); // 正式使用时使用$message提示
}

// 公共逻辑处理
async function request(method, path, data, config = {}, type = "json", timeout=20000) {
  if (!(typeof method === "string" && ["get", "post", "delete", "put"].includes(method)) || !(typeof path === "string") || !(!data || typeof data === "object") || !(typeof config === "object") || !(typeof type === "string")) {
    errorCallBack();
    return;
  }
  const controller = new AbortController();
  const configDefault = { headers: {},singal: controller.signal() };
  method = method.toUpperCase();
  let initConfig;
  let url = path.startsWith("http") ? path : baseURL + path;
  const token = localStorage.getItem("token");
  if (token) configDefault.headers.authorization = "Bearer " + localStorage.getItem("token"); // 这里的authorization怎么赋值要看服务端的设置
  if (method === "get") {
    initConfig = { ...configDefault, ...config };
    const params = data
      ? JSON.stringify(data)
          .replace(/:/g, "=")
          .replace(/"/g, "")
          .replace(/,/g, "&")
          .match(/\{([^)]*)\}/)[1]
      : ""; // 有问题就使用qs开源库处理
    if (params) url += `${url.includes("?") ? "&" : "?"}${params}`;
  } else {
    const body = data && ["json", "text", "blob"].includes(type) ? JSON.stringify(data) : data; // json file text
    initConfig = data ? { ...configDefault, ...config, method, body } : { ...configDefault, ...config, method };
  }
  if (["json", "text", "blob"].includes(type)) initConfig.headers["Content-Type"] = "application/json";
  const id = setTimeout(()=> {controller.abort()}, timeout)
  const response = await fetch(url, initConfig);
  clearTimeout(id)
  // response.status [200,300)
  if (response.ok) {
    if (["text"].includes(type)) return response.text();
    if (["blob"].includes(type)) return response.blob();
    if (["arrayBuffer"].includes(type)) return response.arrayBuffer();
    return response.json();
  }
  // 也可以塞入对token失效等情况的判断以及处理逻辑
  errorCallBack("Something went wrong on API server!");
  throw new Error("Something went wrong on API server!");
}

export function get(path, params, options = { type: "json" }) {
  const config = options.config || {};
  const type = options.type || "json";
  const timeout = options.timeout || 20000
  return request("get", path, params, config, type, timeout);
}
export function post(path, params, options = { type: "json" }) {
  const config = options.config || {};
  const type = options.type || "json";
  const timeout = options.timeout || 20000
  return request("post", path, params, config, type, timeout);
}

测试使用

// 使用
import { get, post } from "./fetch.js";
export function loginUser(opts) { // 表单数据上传
  return post("/user/login", opts);
}
export function testUser() { // 后端返回的data为字符串
  return get("/user/username", null, { type: "text" });
}
export function uploadfile(opts) { // 上传文件
  return post("/plate/file", opts, { type: "file" });
}
export function getfile(opts) { // 下载文件
  return post("/plate/test", opts, { type: "blob" });
}

你可能感兴趣的:(js高级,javascript)