> 文章列表 > 封装一个 axios url encoding serialize util

封装一个 axios url encoding serialize util

封装一个 axios url encoding serialize util

封装一个 axios url encoding serialize util

该 util 遵从的是 Json API,即 swagger, 这一规范,可以将对应的 query 进行 encoding。

主自用,使用 TS,参考对象为 lodash-contrib。


axios 默认传递到后台的数据为 json 格式,官方在文档:URL-Encoding Bodies 中建议在浏览器环境下可以直接使用 URLSearchParams 或是 qs,使用方法如下:

  1. URLSearchParams

    const params = new URLSearchParams();
    params.append('param1', 'value1');
    params.append('param2', 'value2');
    axios.post('/foo', params);
    
  2. qs

    const qs = require('qs');
    axios.post('/foo', qs.stringify({ bar: 123 }));
    

    ES6:

    import qs from 'qs';
    const data = { bar: 123 };
    const options = {method: 'POST',headers: { 'content-type': 'application/x-www-form-urlencoded' },data: qs.stringify(data),url,
    };
    axios(options);
    

我们的 JSON 规范遵从的是这一条:Json API,直接使用 URLSearchParams 好像是行不通的,因为有一些 filter 会使用 [],如:/author/1/book?filter[book]=genre=='Science Fiction';title==The*;price.total>100.00,之前直接使用 URLSearchParams 似乎就报错了。

当然,也有可能是因为 encoding 没有完全转换的关系。

出于同样的原因,直接使用 qs 也存在一定的问题,似乎可能是因为需要重新修改 encoder、queryPrefix 等因素,总之没有能够在有限的时间内完成调整。

最终还是稍微修改了一下 lodash-contrib 中的 toQuery,具体实现如下:

import _ from 'lodash';// some of the util functions are from lodash-contrib but in TS form, credit: https://github.com/node4good/lodash-contrib
// recreated here due to lodash-contrib does not have TS support and cannot be used in the project.
type validQuery = string | number | boolean;type validQueryObj =| { [key: string]: validQuery | validQueryObj }| validQuery[]| validQuery;const buildParams = (prefix: string | number,val: validQueryObj,top = true
): string => {if (_.isUndefined(top)) top = true;if (_.isArray(val)) {return _.map(val, function (value, key) {return buildParams(top ? key : prefix + '[]', value, false);}).join('&');} else if (_.isObject(val)) {return _.map(val, function (value, key) {return buildParams(top ? key : prefix + '[' + key + ']', value, false);}).join('&');} else {return encodeURIComponent(prefix) + '=' + encodeURIComponent(val);}
};export const toQuery = function (obj: validQueryObj): string {return buildParams('', obj);
};

使用方式如下:

export const fetch = async ({apiMethod,uri,params,
}: FetchProps): Promise<AxiosResponse<any, any>> => {return await axiosInstance({method: apiMethod,url: uri,params,paramsSerializer: (params) => {return toQuery(params);},});
};

type guard 目前不是最好的实现,还是需要根据 generics 进行对应的修改,不过这应该算是一个比较通用的解决方案了。