C/C++教程

设计模式|项目实战|封装fetch(2)

本文主要是介绍设计模式|项目实战|封装fetch(2),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前言

前文传送地址:

前端设计模式之工厂模式

前端设计模式之代理模式

前端设计模式之策略模式

前端设计模式之装饰模式

前端设计模式|封装fetch(1)

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

(小声BB,某人的埋点博客终于快到尾声了)

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

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

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

封装 fetch 业务部分

业务层普通封装

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

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

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 层再做一层业务报错封装。

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 层改造如下

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 风格封装的接口,如果还是按照上面的封装,会显得比较累赘,我们可以如下封装一下

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,把数据处理方法也放入对象里面,改造如下

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 一下,后续会根据设计模式博文的推出,逐步的将此项目继续拓展出来,仅供学习参考。

另外有个疑问,由于后期的项目实战想引入真实的案列,不知道语言偏向于 vue 还是 react,采用哪种来写更好?留言或者加微信都行。

附加信息

如对文章内容以及实例有任何疑问、见解可随时与我沟通。你不点个赞吗O(∩_∩)O~

关于前端早早聊大会

前端早早聊大会目标成为用得上、听得懂、抄得走的技术大会,计划 2020 年办 >= 15 期,由前端早早聊与掘金联合举办,前端早早聊大会行程动态、录播视频/PPT/讲稿资料下载请关注 「前端早早聊」 公众号跟进。


你的支持,是早早聊办下去的唯一动力!
点击保存下图,转发朋友圈即可,越多人参与,越多讲师愿意来分享!
还想听哪方面的分享,直接加 Scott 微信: codingdreamer 提需求吧!

7 月 18 日举办第十二届 - 前端搞可视化,报名请戳:www.huodongxing.com/go/tl12 ,海报及讲师行程如下:

第十二届大会讲师出场预告图 (2).png

这篇关于设计模式|项目实战|封装fetch(2)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!