(共556篇)
全部分类

接口数据处理规范
[ 未分类 ] 

基本封装

接口数据在前端处理是最麻烦的, 每次调用接口, 前端都需要针对接口的各种状态, 作出相应的处理, 错过任何中可能的类型, 都可能导致在页面中暴露不安全的信息, 比如后端抛出的运行错误等信息.

下面是某个接口的返回数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// XMLHTTPResponse
{
  data: {
    timestamp: 1646450333874, 
    status: "success", 
    code: null, 
    message: "成功", 
    content: {}
  },
  errMsg: "request:ok",
  header: {
    cache-control: "no-cache, no-store, max-age=0, must-revalidate", 
    content-type: "application/json", 
    expires: "0", 
    pragma: "no-cache"
  },
  statusCode: 200
}

在这个案例中, 接口状态分为两类,

  1. 网络层状态
  2. 业务层状态

网络层状态 , 指的是statusCode的值, 表示HTTP请求相应代码, 这一类的状态, 一般来说除了code 200, 其他所有的code, 都属于接口请求失败的范畴 ,

业务层状态, 指的是 data.code的值, 它表示后端在处理相关业务时的结果状态, 具体的值是由后端开发人员指定的, 在目前的业务中, 已经出现的状态有5类

data.code desc 处理方式
null 业务处理正常

400|一般指参数异常,|这类信息,一般都是可预判性的错误信息, 比如手机号码格式错误, 字符数量超过限制等, 大部分可以知己以弹窗的方式提示给用户 401|一般指请求接口时缺少用户信息(token), |通常会引导用户重新登录 403|一般指请求接口时附带的用户信息没有相关权限|可能会引导用户重新登录或者提示用户没有相关权限 5xx|业务处理过程中出现了异常信息, 这类信息|这类信息一般都是不可预判性的错误信息, 只能用来解决接口中出现的问题, 不能暴露给用户页面

知道了上面这些状态信息, 我们就应该知道如何去实现网络请求的基础类了, 大致思路如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// http.js
export function http(){
  return new Promise((resolve, reject)=>{
        const res = {
        // ajax返回的基础数据
      };
      if(res.statusCode !== 200){
        // 只要是200以外的状态, 这个接口直接可以当做失败
        reject()
        return
      }
    
        // 这里只处理res.data.code为null的情况
        if(!res.data.code){
        // 把res.data内容返回,请求接口的地方在取值的时候,可以少取一层
        resolve(res.data);
        return
      }
        
        if(res.data.code===401){
        // 通常在这种情况下, 会选择自动跳转到登录页, 等待用户登录成功后再自动跳转回当前页面
        return 
      }
    
      reject(res.data)
  })

请求接口的地方:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

import { http } from './http'

async function getNewsList(){
      try{
      const res = await http(url, data, method);
      // 处理正常情况下的res内容, 这里可能在处理数据时, 抛出不可预测性的异常
    }catch(e){
      console.log(e);
      // 这里要处理所有的reject
    }
}

上面的catch代码块中 需要处理的异常包含以下几类

  1. statusCode!==200的情况
  2. statusCode===200 && data.code!=null的情况 a. data.code===400 b. data.code===403 c. data.code===5xx
  3. try中在处理数据过程中可能出现的异常

所以catch中应当这么处理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

import { http } from './http'

async function getNewsList(){
      try{
      const res = await http(url, data, method);
      // 处理正常情况下的res内容, 这里可能在处理数据时, 抛出不可预测性的异常
    }catch(error){
      console.log(error);
      if(e.code === 403){
        // 需要重新登录还是需要弹窗提示, 根据产品需求来执行
        return 
      }
      
      /* 
      这句用来处理403之外的所有异常
      statusCode !== 200时, error的值是undefined, 会弹窗提示自定义的错误内容
         res.data.code === 5xx时, 也会弹窗提示自定义的错误内容
      try中可能出现的异常信息, error虽然不是undefined, 但它里面通常不会包含code字段
      */
      this.$alert(error.code && error.code==400 ? error.msg :'自定义错误内容')
    }
}

接口数据中的布尔值处理

目前在很多项目中, 对于标识符一类的字段, 在mysql中都以 String Y和 N来存储, 而对于前端来说, 这种字段使用true或者false更方便, 以往封装好的http类中, 会在接收数据时, 对所有的String Y 和 N转换成true与false, 发送数据时, 再把 true/false转为字符串.

虽然目前没有大的问题, 但对于富文本功能来说, 如果富文本中出现了Y与N字符, 保存的时候也会被转成字面量true与fasle, 依然有较大的隐患

因此, 基于降低功能耦合度的考虑, 把Request与Response中是否转换String Y与N的问题, 进行单独封装, 保存在/utils/index.js中, 需要的时候自行调用即可

解析 Response 中的的数据:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

export function mapRes(data, isArrayYItem = false) {
  // 格式化接收到的数据, 主要是把'Y'改成true, 'N'改成false
  if (!isArrayYItem && data === "Y") {
    return true;
  }
  if (!isArrayYItem && data === "N") {
    return false;
  }
  if (typeof data !== "object") {
    return data;
  }

  // 数组
  if (Array.isArray(data)) {
    return data.map((item) => mapRes(item, true));
  }

  // map对象
  for (const k in data) {
    data[k] = mapRes(data[k]);
  }
  return data;
}

解析Request中的数据:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

export function mapReq(data, isArrayYItem) {
  // 格式化即将发送的数据, 主要是把true改成'Y', false改成'N'
  if (!isArrayYItem && data === true) {
    return "Y";
  }
  if (!isArrayYItem && data === false) {
    return "N";
  }
  if (typeof data !== "object") {
    return data;
  }

  // 数组
  if (Array.isArray(data)) {
    return data.map((item) => mapReq(item, true));
  }

  // map对象
  const obj = {}
  for (const k in data) {
    obj[k] = mapReq(data[k]);
  }
  return obj;
}

页面缺省图展示

页面内缺省图是很常用的东西, 比如在打开一个商品详情页时, 可能出现以下几种情况

  1. 商品正常, 页面显示正常的商品属性
  2. 商品已下架, 页面显示已下架的缺省图
  3. 商品不存在, 页面显示商品不存在的缺省图

大致的结构如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <div class="page_root">
    <div v-if="!pageStatus" class="item_placeholder">骨架图</div>    
    <div class="item_lost">商品不存在</div>    
    <div class="item_down">商品已下架</div>    
    <div class="item_detail">商品详情</div>    
  </div>
</template>
<script>
  export default {
    data(){
      return {
          pageStatus:0  
      }
    },
    mounted(){
      getItemDetail().then(res=>{
        if(商品不存在)
      })
    }
  }
</script>