fetch的二次封装

前言

在请求方法这块,考虑到便捷性,针对不同的平台app web h5以及对参数的处理,做了以下的方法封装。

内容

1.请求参数处理
2.响应code处理
3.处理数组、对象等特殊参数
4.跨域请求mode
5.拓展

执行
请求参数处理

这里主要使用到三种请求头类型:multipart/form-data、application/json、application/x-www-form-urlencoded,针对不同的类型对参数做不同的处理

/**
 * @param {*} params 
 * @param {*} ContentType 
 */
function getUriParams(params = {}, contentType = 'multipart/form-data') {
    // 请求参数
    let uriParams = ''
    switch (contentType) {
        case 'multipart/form-data': // formData
            uriParams = new FormData()
            Object.keys(params).forEach(key => {
                uriParams.append(key, params[key])
            })
            break
        case 'application/json': // json
            uriParams = JSON.stringify(params)
            break
        case 'application/x-www-form-urlencoded': // 键值对 key1=value1&key2=value2
            Object.keys(params).forEach(key => {
                uriParams += key + '=' + params[key] + '&'
            })
            uriParams = uriParams.substring(0, uriParams.length - 1)
            break
        default:
            break
    }
    return uriParams
}
响应code处理

常用的200 404 500...,以及项目中单独定义的。

/**
 * @param {Object} respResult 
 * @param {Function} resolve 
 * @param {Function} reject 
 */
function responseCode(respResult = {}, resolve, reject) {
    switch (respResult.code) {
        case 200: // 成功
            resolve(respResult.ret)
            break
        case 404: // 请求资源不存在
            resolve({ msg: '请求资源不存在' })
            break
        case 500: // 服务器异常
            resolve({ msg: '服务器异常' })
            break
        // 以下为项目中接口定义的code
        case xxx: // 鉴权失败
            doLogin()
            break
        // ... ... 
        default:
            reject(respResult)
            break
    }
}
处理数组、对象等特殊参数

在请求类型为formData时,请求携带参数格式为

  id = 1
  value = '1234'
  // ... ...

当后端接受类型存在Map List时,我们的请求参数格式可能为

params = {
  list1: [1,2,3,4],
  list2: [{id: 1, value: '1234'}],
  obj1: {id: 1, value: '1234'}
  // ... ...
}

而我们知道需要将数据调整成下面的方式才能被后端所识别

params['list1'][0] = 1
params['list1'][1] = 2
// ... ...
params['list2'][0]['id'] = 1
params['list2'][0]['value'] = '1234'
// ... ...
params['obj1']['id'] = 1
params['obj1']['value'] = '1234'
// ... ...

注意:针对图片格式则不用做相应处理

/**
 * 参数处理(处理数组或对象的value,格式:数组arr[i]、对象obj.key)
 * @param {*} params 
 */
function manageParams(params) {
    for (let key in params) {
        let item = params[key]
        if (item && item !== '' && item !== null && item !== undefined) {
            if (Array.isArray(item)) {
                // 数组
                item.forEach((val, i) => {
                    if (val.constructor === Object || val.constructor === File || typeof val === 'string' || typeof val === 'number') {
                        params[`${key}[${i}]`] = val
                    }
                })

                delete params[key]
                manageParams(params)
            } else if (item.constructor === Object && !isImgFile(item)) {
                // 对象
                for (let i in item) {
                    params[`${key}.${i}`] = item[i]
                }
                delete params[key]
                manageParams(params)
            }
        }
    }

    let allString = false
    for (let key in params) {
        let item = params[key] || ''
        if (typeof item === 'string' || typeof item === 'number' || item === null || item.constructor === File) {
            allString = true
        }
    }
    if (allString) {
        return params
    }
}

// 非图片
function isImgFile(obj) {
    if (obj['size'] && obj['type'] && obj['name']) {
        return true
    }
    return false
}
跨域请求mode

fetch支持cors进行跨域访问,但如果header中需要携带参数,会进行一个预检的过程,需要服务端设置允许请求头携带参数

// ... ...
let headers = new Header()
headers['Access-Control-Allow-Origin'] = '*'
headers['Content-Type'] = 'xxx'
// ... ...
fetch(url, {
   method: 'POST',
   headers,
   mode: 'cors',
   body: getUriParams(manageParams(params)),
}).then(() {
    // ... ...
})
// ... ...

服务端设置

setHeader('Access-Control-Allow-Headers: Content-Type ... ...');
拓展

根据项目具体情况
1.参数可能放于body或者header

return new Promise((reject, resolve) => {
  fetch(url, {
     method: 'POST',
     headers: {
        'Content-Type': ContentType,
        platformType: 2,
        osType: '',
        version: ''
        // ... ...
     },
     body: getUriParams(manageParams(params)),
     credentials: 'include'
  }).then((response) => {
     Fetch.Fetch_last_url[url] = null
     if (response.ok) {
         return response.json()
      } else {
         reject({success: false, errCode:'500', errDesc: '服务器异常,请稍后重试'})
      }
   }).then((respResult) => {
        responseCode(respResult, resolve, reject)
   }).catch((error) => {
        reject({success: false, errCode:'500', error: error.errDesc})
   })
})

2.可能会使用到签名校验

function getSign(params) {
    const CryptoJS = require('crypto-js')
    // 密钥
    let secret = '3f3**************************216'  // 默认固定密钥
    // 排序、加密(签名字段按照key正序,前后拼接密钥,MD5)
    let paramsKeys = [], allParams = secret
    Object.keys(params).forEach(key => paramsKeys.push(key))
    paramsKeys.sort()
    paramsKeys.forEach((key) => allParams += key + '=' + params[key] + '&')

    allParams = allParams.substring(0, allParams.length - 1) + secret
    return CryptoJS.MD5(allParams).toString()
}

3.请求和响应参数可能会进行加解密

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353