fetch封装
浮川的小窝

fetch封装

面壁人浮川
2023-11-15 / 0 评论 / 9 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年11月15日,已超过183天没有更新,若内容或图片失效,请留言反馈。

Fetch-API.png


/**
 * @Author       : Xiao Xiang Lun
 * @Date         : 2023-11-15 15:57:06
 * @LastEditors  : snowlove xiaoxl@botech.com.cn
 * @LastEditTime : 2023-11-15 16:31:45
 * @FilePath     : /react/demo/src/views/DemoStoreTwo/fetchReq.js
 * @Environment  : mac node v16.3.0
 * @Description  : 
 * @关注作者请访问 https://snowlove.synology.me:5 
 * @备用地址:https://nas.snowlove.top:5
 */
/*
 http([config])
   + url 请求地址
   + method 请求方式  *GET/DELETE/HEAD/OPTIONS/POST/PUT/PATCH
   + credentials 携带资源凭证  *include/same-origin/omit
   + headers:null 自定义的请求头信息「格式必须是纯粹对象」
   + body:null 请求主体信息「只针对于POST系列请求,根据当前服务器要求,如果用户传递的是一个纯粹对象,我们需要把其变为urlencoded格式字符串(设定请求头中的Content-Type)...」
   + params:null 设定问号传参信息「格式必须是纯粹对象,我们在内部把其拼接到url的末尾」
   + responseType 预设服务器返回结果的读取方式  *json/text/arrayBuffer/blob
   + signal 中断请求的信号
 -----
 */
//  import qs from 'https://cdn.bootcdn.net/ajax/libs/qs/6.11.2/qs.min.js';
 const class2type = {},
  toString = class2type.toString,
  hasOwn = class2type.hasOwnProperty,
  isPlainObject = function isPlainObject(obj) {
    let proto, Ctor;
    if (!obj || toString.call(obj) !== "[object Object]") return false;
    proto = Object.getPrototypeOf(obj);
    if (!proto) return true;
    Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
    return typeof Ctor === "function" && Ctor === Object;
  },
  qsStringify = function qsStringify(obj) {
    const params = [];
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        const value = obj[key];
        const encodedKey = encodeURIComponent(key);
        const encodedValue = encodeURIComponent(value);
        params.push(`${encodedKey}=${encodedValue}`);
      }
    }
    return params.join('&');
  }
 
 /* 核心方法 */
 const http = function http(config) {
   if (!isPlainObject(config)) config = {};
   const controller = new AbortController();
   config = Object.assign({
     url: '',
     method: 'GET',
     credentials: 'include',
     headers: null,
     body: null,
     params: null,
     responseType: 'json',
     signal: (controller && controller.signal) || null,
   }, config);
   if(config.abort || config.abort instanceof Promise) {
     config.abort().then((_)=>controller.abort())
    }
   if (!config.url) throw new TypeError('url must be required');
   if (!isPlainObject(config.headers)) config.headers = {};
   if (config.params !== null && !isPlainObject(config.params)) config.params = null;
 
   let { url, method, credentials, headers, body, params, responseType, signal } = config;
   // 处理问号传参
   if (params) {
     url += `${url.includes('?') ? '&' : '?'}${qsStringify(params)}`;
   }
 
   // 处理请求主体信息:按照我们后台要求,如果传递的是一个普通对象,我们要把其设置为urlencoded格式「设置请求头」?
   if (isPlainObject(body)) {
     body = qsStringify(body);
     headers['Content-Type'] = 'application/x-www-form-urlencoded';
   }
 
   // 发送请求
   method = method.toUpperCase();
   config = {
     method,
     credentials,
     headers,
     cache: 'no-cache',
     signal
   };
   if (/^(POST|PUT|PATCH)$/i.test(method) && body) config.body = body;
   return fetch(url, config)
     .then(response => {
       let { status, statusText } = response;
       if (/^(2|3)\d{2}$/.test(status)) {
         // 请求成功:根据预设的方式,获取需要的值
         let result;
         switch (responseType.toLowerCase()) {
           case 'text':
             result = response.text();
             break;
           case 'arraybuffer':
             result = response.arrayBuffer();
             break;
           case 'blob':
             result = response.blob();
             break;
           default:
             result = response.json();
         }
         return result;
       }
       // 请求失败:HTTP状态码失败
       return Promise.reject({
         code: -100,
         status,
         statusText
       });
     })
     .catch(reason => {
       return Promise.reject(reason); //统一处理完提示后,在组件中获取到的依然还是失败
     });
 };
 /* 快捷方法 */
 ["GET", "HEAD", "DELETE", "OPTIONS"].forEach(item => {
   http[item.toLowerCase()] = function (url, config) {
     if (!isPlainObject(config)) config = {};
     config['url'] = url;
     config['method'] = item;
     return http(config);
   };
 });
 ["POST", "PUT", "PATCH"].forEach(item => {
   http[item.toLowerCase()] = function (url, body, config) {
     if (!isPlainObject(config)) config = {};
     config['url'] = url;
     config['method'] = item;
     config['body'] = body;
     return http(config);
   };
 });
 
 export default http;

调用方法 如需中断链接 传入abort回调 在其中重写逻辑 注意返回一个promise

http.get(' https://snowlove.synology.me:6002/mock/6553259ddb7e05001d99be09/example/query',{
  abort:()=>new Promise((reslove)=>{
    console.log("abort1")
    reslove(true)
  })
}).then(res=>{
  console.log(res)
}).catch(err=>{
  console.log("捕捉主动终止错误")
})
http.get(' https://snowlove.synology.me:6002/mock/6553259ddb7e05001d99be09/example/query',{
abort:()=>new Promise((reslove)=>{
  console.log("abort2")
  setTimeout(() => {
    reslove(true)
  }, 1000);
})
}).then(res=>{
console.log(res)
}).catch(err=>{
console.log("捕捉错误2")
})

/**
* abort1
* abort2
* 捕捉错误
*/
0

评论 (0)

取消