前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >项目实战|业务处理层实现

项目实战|业务处理层实现

作者头像
Cookieboty
发布2020-10-23 15:06:50
4150
发布2020-10-23 15:06:50
举报
文章被收录于专栏:前端小兵成长营

前言

连续四篇设计模式都是前端经常使用到的,相信大家参考博文中的项目实战之后再去琢磨自己的项目代码、或者看一些优秀的开源代码对比后,能更深刻的体会到设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结这句话的含义。

在开发的过程中,同一种功能采用不同的或者组合的设计模式实现,可以将代码质量提升。这里要 copy 第一篇博文的话重申一下为什么前端需要了解设计模式

在日常开发中大部分前端都在开发的中,进行组件、方法等封装、提炼的时候或多或少已经使用了一些设计模式的理念, 但是由于对设计模式的概念模糊,理解不够,从而导致设计整体架构的时候,会有各种局限性,拓展性、可读性、维护性变差,不得不多次重构甚至重写。在 ts 在前端开发中加速推进的同时,合理的设计模式使得项目从架构、设计、迭代、维护都有一定质量的保障。

接下来我们通过使用设计模式中的工厂、代理模式来继续改造我们的 fetch 工程

封装 fetch 业务部分

业务层普通封装

业务层的封装,我们在上一篇的文末已经提到过,这边再结合代码展示一下

一般来说我们的工程会有多个模块,这边我们先根据各个模块封装一层 service 层,方便我们业务侧调用。

代码语言:javascript
复制
import Fetch from './util/fetch';

const prefix = 'https://api.github.com/users'

const fetch = new Fetch({ requestType: "JSON", cacheType: 'local', BASE_URL: prefix });

const getUser = (params) => {
  return new Promise((resolve, reject) => {
    fetch.get({
      url: '/octocat',
      params
    }).then(response => {
      const { data, code, errMessage } = response
      if (code) {
        resolve(data)
      } else {
        reject(errMessage)
      }
    })
  })
}

const setUser = (params) => {
  return new Promise((resolve, reject) => {
    fetch.post({
      url: '/octocat',
      params
    }).then(response => {
      const { data, code, errMessage } = response
      if (code) {
        resolve(data)
      } else {
        reject(errMessage)
      }
    })
  })
}

export {
  getUser,
  setUser
};
export default {
  getUser,
  setUser
}

如上我们封装了一个用户 service 层,一般来说,除了正常的 http 的请求状态异常之外,会有业务处理的异常。所以在 service 层调用的时候,可以预先处理掉错误的异常,返回给业务侧正常的数据,业务侧在调用的时候,可以直接使用 try/catch 去承接数据。同时在多个业务侧都需要调用相同的接口的时候,可以在用户 service 层处理、过滤一些后台返回的参数,这样可以使得业务侧调用到方便前端展示的数据(比如组装列表数据,日期、金额格式化等)。

但是当业务过多,都要处理统一的业务错误的时候,会显得非常麻烦,造成冗余代码跟维护困难,所以在这之上,我们可以在针对 service 层再做一层业务报错封装。

代码语言:javascript
复制
import Fetch from '../util/fetch';

const prefix = 'https://api.github.com'

const fetch = new Fetch({ requestType: "JSON", cacheType: 'local', BASE_URL: prefix });

const get = (url, params) => {
  return new Promise((resolve, reject) => {
    fetch.get({
      url,
      params
    }).then(response => {
      const { data, code, errMessage } = response
      if (code) {
        resolve(data)
      } else {
        reject(errMessage)
      }
    })
  })
}

export {
  get
};

export default {
  get
}

如上可以将业务层的统一处理跟单独的业务接口数据处理分开,用户的 service 层改造如下

代码语言:javascript
复制
import { get, post } from './baseFetch';

const prefix = 'users'

const getUser = async (params) => {
  try {
    const data = get({
      url: `${prefix}/octocat`,
      params
    })
    return data
  }
}

const setUser = (params) => {
  try {
    const data = post({
      url: `${prefix}/octocat`,
      params
    })
    return data
  }
}

export {
  getUser,
  setUser
};

export default {
  getUser,
  setUser
}

业务层 restful 格式封装

有些后台接口是按照 restful 风格封装的接口,如果还是按照上面的封装,会显得比较累赘,我们可以如下封装一下

代码语言:javascript
复制
import baseFetch from './baseFetch';

const prefix = 'users'

const methods = ['get', 'post', 'put', 'delete']

const userUrl = {
  users: 'octocats',
  user: 'octocat'
}

const user = {}
Object.keys(userUrl).forEach(key => {
  user[key] = {}
  methods.forEach(method => {
    user[key][method] = (params) => {
      return baseFetch[method](`${prefix}/${userUrl[key]}`, params)
    }
  })
})

export {
  user
};

export default {
  user
}

user.user.get({ test: 1 }) // 业务侧调用
user.user.post({ test: 1 }) // 业务侧调用

如上我们将 url 跟请求方法组装起来,业务侧调用会简便很多,但是中间的业务层数据处理似乎就没了,我们可以将 userUrl 拓展成 userObj,把数据处理方法也放入对象里面,改造如下

代码语言:javascript
复制
const userObj = {
  users: {
    url: 'octocats',
    get(data) { return data }
  },
  user: {
    url: 'octocats',
    post(data) { return data }
  }
}

const user = {}
Object.keys(userObj).forEach(key => {
  user[key] = {}
  methods.forEach(method => {
    user[key][method] = (params) => {
      return new Promise((resolve) => {
        baseFetch[method](`${prefix}/${userObj[key].url}`, params).then(data => {
          if (userObj[key][method]) resolve(userObj[key][method](data))
          resolve(data)
        })
      })
    }
  })
})

尾声

完整的 demo 地址:项目实战 demo,喜欢的朋友可以 star 一下,后续会根据设计模式博文的推出,逐步的将此项目继续拓展出来。

如对文章内容以及实例有任何疑问、见解可添加微信 沟通。

另外关注公众号 Cookieboty1024,欢迎加入前端小兵成长营

手动狗头镇楼

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端小兵成长营 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 封装 fetch 业务部分
    • 业务层普通封装
      • 业务层 restful 格式封装
      • 尾声
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档