Typescript封裝框架(一) 網絡請求篇

如何封裝網絡請求框架

年末的時候用了typescript做新項目,還是學到很多,記錄一下,學了之後,先是學了下如何將Axios改成Typescript版本的,Typescript在我的理解是加了類型的限制,八月份面試的時候,有個人問我,ts和js有什麼不同?

大概是強類型更加規範,對面向對象支持比較好.因爲大學學的是JAVA搞過幾年安卓,所以對面向對象的語言很有好感,到現在我還是覺得JAVA很規範,我是不是對不住web前端?我是真在安卓上學到很多.

當然對ts,到現在我也不能講出一朵花,一直寫業務,說實話,沒時間去反思.個人還沒什麼深刻的理解,不過會帶着這個問題去學習.

正題,不廢話.

單例模式創建AXIOS實例

一般來說,基本地址是固定的,全局使用,就需要用單例,只讓其分配一次,單例有懶餓漢,做前端很少涉及線程的,所以就不用考慮加鎖保持變量只被一個線程訪問之類,除非業務有需求,例如:支付業務平臺和普通業務平臺是分開的

static關鍵字不能少,static優先於對象存在,可通過類名直接訪問,因爲this指向是實例,所以這裏不能用this訪問,如果不加上static,則實例不是全局的,每一次請求都會生成,而設置爲static類全局變量,隨着類加載去產生,只會生成一次.私有化,只有類本身才能改變其值.

如何深入理解static關鍵字,研究js的內存管理之後去說

class NetWorkUtils {
  private static instance: AxiosInstance | null = null;
    constructor() {
    if (NetWorkUtils.instance === null) {
        NetWorkUtils.instance = axios.create({
              baseURL: process.env.VUE_APP_URL,
              timeout: 50000, // request timeout
            });
       }
        //TODO 
        //可配置下請求攔截器
   }
}

針對多個平臺基地址不同,baseURL作爲參數,導出對象供使用,仍然能保持全局唯一,去掉static關鍵字

export const NetWorkUtil = new NetWorkUtils(process.env.VUE_APP_URL);
export const NetWorkPayUtil = new NetWorkUtils(process.env.VUE_APP_PAY_URL);

響應父實體類

響應數據的格式往往統一,data裏面的類型多種形態,用泛型代替,到時候反射爲原類型

export default interface BaseResponse<T = any> {
  code: string;
  data: T;
  msg: string;
}

聲明類型準備上

declare type Methods =
  | 'get'
  | 'GET'
  | 'delete'
  | 'DELETE'
  | 'head'
  | 'HEAD'
  | 'options'
  | 'OPTIONS'
  | 'post'
  | 'POST'
  | 'put'
  | 'PUT'
  | 'patch'
  | 'PATCH';

規定返回類型爲AxiosPromise

import axios, {
  AxiosInstance,
  AxiosPromise,
  AxiosRequestConfig,
  AxiosResponse,
} from 'axios';

axios.defaults.withCredentials = true;

//後端不支持RESTful接口,如果支持還可以使用Record定義每個方法,然後去實現
declare type Methods =
  | 'get'
  | 'GET'
  | 'post'
  | 'POST'

/**
 * transformRequest 函數數組
 */
interface Config {
  data?: any;
  params?: any;
  url?: string;
  headers?: any;
  responseType?: string;
  transformRequest?: Array<any>;
}

class NetWorkUtils {
  private instance: AxiosInstance | null = null;

  constructor(url:string) {
    if (this.instance === null) {
      this.instance = axios.create({
          baseURL: url,
          timeout: 5000, // request timeout
        });
      this.initInterceptors();
    }
  }

  /**
   * 初始化請求響應的攔截器
   */
  private initInterceptors(): void {
    this.instance!.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        const sid = window.localStorage.getItem('sessionId');
        if (sid) {
          Object.assign(config.headers, { sessionId: sid });
        }
        return config;
      },
      error => {
        Promise.reject(error);
      }
    );

    this.instance!.interceptors.response.use(
      (response: AxiosResponse) => {
        return response;
      },
      error => {
        return error;
      }
    );
  }
  /**
   * @param {string} url 請求連接
   * @param {string} method HTTP方式
   * @param {any} data 數據
   * @returns {Promise} 返回的異步
   */
  createAPI<T,R>(url: string, method: Methods, data?: T): AxiosPromise<R> {
    const config: Config = {};
    if (method === 'get' || method === 'GET') {
      config.params = data;
    } else {
      config.data = data;
    }
    return this.instance!(Object.assign(config, { method, url }));
  }

  createFormAPI<T>(
    url: string,
    method: Methods,
    data?: T,
    responseType?: string
  ): AxiosPromise {
    if (!responseType) {
      responseType = 'json';
    }
    const config: Config = {
      data: data,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      responseType,
      transformRequest: [],
    };
    config.transformRequest = [
      function(data: { [x: string]: string | number | boolean }) {
        let ret = '';
        for (const key in data) {
          ret += `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}&`;
        }
        return ret;
      },
    ];
    return this.instance!(Object.assign(config, { method, url }));
  }
}

export const NetWorkUtil = new NetWorkUtils(process.env.VUE_APP_URL);
export const NetWorkPayUtil = new NetWorkUtils(process.env.VUE_APP_PAY_URL);

創建請求 
export async function login(data: IUserParam): Promise<BaseResponse<IUser>> {
  return (await NetWorkUtil.createAPI('/登錄', 'GET', data))
    .data;
}

以上均爲我不成熟的代碼.各位根據需求來

如果支持RESTful方法,可以利用Record改成如下方式

enum IHttpMethods {
    GET = 'get',
    POST = 'post',
    DELETE = 'delete',
    PUT = 'put',
}

const methods = ["get", "post", "delete", "put"];

interface IHttpFn {
    <T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
}

type IHttp = Record<IHttpMethods, IHttpFn>;

const httpMethods: IHttp = methods.reduce((map: any, method: string) => {
    map[method] = (url: string, options: AxiosRequestConfig = {}) => {
        const { data, ...config } = options;
        return (axios as any)[method](url, data, config)
            .then((res: AxiosResponse) => {
                if (res.data.errCode) {
                    //todo somethins
                } else {
                    //todo somethins
                }
            });
    }
    return map
}, {})

export default httpMethods;
————————————————
版權聲明:本文爲CSDN博主「問白」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_38080573/article/details/92838045

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章