zoukankan      html  css  js  c++  java
  • 全栈之路-杂篇-前端Http请求封装优化

      在项目开发过程中,代码的封装是很有必要的,我觉得这是程序员进阶的一个重要的技能,不会封装代码,你的代码看起来乱的一批,基本上不能维护,像一次性塑料袋一样,用完一次就失去了价值,这同时也会无缘无故的增加项目的总体的代码量,重复代码的不断叠加,谁也是这么一步一步走过来的,但是我要学着去改变,主要是学习这其中的思想,从一个简单的http请求的处理来看看如何进行代码的封装,让你的代码优雅。

    一、烂透了的代码

    简单说一下,这个场景是什么,就是从服务器请求接口,将数据展示到页面上,很简单,也是最常用的,最基础的功能,先看看一段最烂的代码,不是说有多烂,只是说实现了功能,其他的地方一无是处的,哈哈,下面是微信提供的请求数据的API

     1  wx.request({
     2       url: '接口的地址url',
     3       data: {
     4           names:'t-1'
     5       },
     6       method: 'GET', 
     7       header: {
     8           appkey:'your appkey'
     9       }, 
    10       success: res=>{
    11           this.setData({
    12               topTheme:res.data[0]
    13           })
    14       }
    15  })
    16     

    我写了挺长时间的代码了,我发现一直以来,都是这么写的,没有什么封装,擦!这段代码本身没有问题,功能也实现了,但是让人看起来很不爽,后期的维护很费劲,而且随着项目的开发进行,没有用处的垃圾代码会直线上升,这其实是可以优化的,看看有哪些地方是可以进行优化的?

    二、不是那么烂了

    优化可以试着从下面几点入手:

    1、常量配置化

    像url地址、appkey这种是通用的,最起码url的域名是通用的,可以写到一个单独的配置文件中,这样的话,很好维护,就像这样子:

     1 const config = {
     2     appkey:'your appkey',
     3     apiBaseUrl:'通用的url地址'
     4 }
     5 // ES6的语法导出
     6 export {
     7     config
     8 }
     9 
    10 // 顺便说一下,其他的js文件如何导入呢?
    11 import {
    12     config
    13 } from "文件的位置。。。";

    2、业务处理的封装

    这个一般会放在单独抽象出来的model层中,也就是项目中的model文件下的js文件中,我们将拆分出来的模块都抽象成一个个的js文件,具体的处理逻辑我们在这里处理,具体操作是在根目录下面新建model文件夹,在model文件夹下新建theme.js文件,代码具体如下:

     1 import {
     2   config
     3 }from '文件位置。。。'
     4 
     5 // 关于主题的相关的业务的处理
     6 class Theme {
     7   // 获取localhostA位置的主题
     8   static getHomeLocationA(callback){
     9     wx.request({
    10       url: `${config.apiBaseUrl}theme/by/names`,
    11       method: 'GET',
    12       header: {
    13         appkey: `${config.appkey}`
    14       },
    15       data: {
    16         names: 't-1'
    17       },
    18       success: res => {
    19         callback(res.data)
    20       }
    21     })
    22   }
    23 }
    24 // 别忘了导出
    25 export {
    26   Theme
    27 }

    在page中我们就能这样引用Theme类中的方法了:

    1 Theme.getHomeLocationA(data =>{
    2    this.setData({
    3      themeA:data[0]
    4    })
    5 })

    看起来并没有简化,反而多增加了一个文件,哈哈,这么想也没什么问题,不反驳,但是优化之路还在继续,这还远远不够呢!

    三、代码看起来整洁多了

    在第二部分的基础上,我们进一步封装代码,将wx.request()进一步封装成一个通用的工具类,进一步优化这个代码!

    1、封装微信小程序的原生API

    我们在utils文件夹中新建http.js文件来做wx.request()的封装,具体代码如下:

     1 // wx.request的封装
     2 import {
     3   config
     4 }from '文件位置。。。'
     5 
     6 class Http{
     7   static request({url,data,callback,method='GET'}){
     8     wx.request({
     9       url: `${config.apiBaseUrl}${url}`,
    10       method: method,
    11       data: data,
    12       header: {
    13         appkey: `${config.appkey}`
    14       },
    15       success: res => {
    16         callback(res.data)
    17       }
    18     })
    19   }
    20 }
    21 // 别忘了导出
    22 export {
    23   Http
    24 }

    2、model层的调用

    model层需要进行简化,至于page页面层,不用做修改

     1 class Theme {
     2   // 获取localhostA位置的主题
     3   static getHomeLocationA(func){
     4     Http.request({
     5       url:'theme/by/names',
     6       data:{
     7         names:'t-1'
     8       },
     9       callback:res=>{
    10         func(res)
    11       }
    12     })
    13   }
    14 }

    这个对异步请求的处理使用callback进行回调的用法基本上就封装完成了,但是你要说这是终极解决方案,那肯定不是,如何处理这个异步回调请求,还是需要优化的,终极解决方案是利用ES6中async和await,这个的本质还是利用Promise对象进行异步请求回调的处理

    四、代码有点优雅

    代码封装的终极解决方案,虽然用了一段创造性的封装小程序原生API,可惜不是我创造的,七月老师写的一段简短的,很有技巧性的代码,如何利用async和await实现异步请求处理,看看代码的实现:

    1、继续封装小程序API

     1 class Http {
     2   static async request({
     3     url,
     4     data,
     5     method = 'GET'
     6   }) {
     7     // 这里的关键是promisc方法,将原生API转换成Promise对象
     8     const res = await promisic(wx.request)({
     9       url: `${config.apiBaseUrl}${url}`,
    10       method: method,
    11       data: data,
    12       header: {
    13         appkey: `${config.appkey}`
    14       }
    15     })
    16     return res.data
    17   }
    18 }

    2、model层调用Http类封装的request方法

    1   // 获取localhostA位置的主题
    2   static async getHomeLocationA(){
    3     return await Http.request({
    4       url:'theme/by/names',
    5       data:{
    6         names:'t-1'
    7       }
    8     })
    9   }

    3、page层调用model层getHomeLocationA方法

    1   onLoad: async function(options) {
    2     // 其实只有这一行的代码,至于其他代码跟这次封装没关系了,一定要async和await一起使用
    3     const data = await Theme.getHomeLocationA()
    4     this.setData({
    5       themeA:data[0]
    6     })
    7   },

    你觉得可能一次请求中代码量并没有少,反而层层的调用,使得代码更多,但是如果是成百上千个请求呢,你难道每一次都像一种多写的那样,不断重复写wx.request请求???哈哈,真香警告

    4、关键的代码promisic()方法

     1 const promisic = function(func) {
     2   return function(params = {}) {
     3     return new Promise((resolve, reject) => {
     4       const args = Object.assign(params, {
     5         success: (res) => { 
     6           resolve(res);
     7         },
     8         fail: (error) => {
     9           reject(error);
    10         }
    11       });
    12       func(args);
    13     });
    14   };
    15 }
    16 
    17 export {
    18   promisic
    19 }

    至于这段代码不做解释,因为我也不是很懂,尴尬了,不过这里用到的是设计模式中的代理模式,封装了一下Promise对象,将原生的API的success和fail函数去执行Promise对象的resolve和reject函数,从而达到封装成Promise对象的目的

    五、终极项目结构

    最终的结构一般会是这样子:

    跟着七月老师继续努力!!!

    七月老师课程链接:https://class.imooc.com/sale/javafullstack

    async和await讲解:https://segmentfault.com/a/1190000011526612

  • 相关阅读:
    linux使用windows中编辑的文件,格式问题
    模拟退火算法c++
    progress第三方框架和二维码第三方框架的选择
    iOS 初始化项目内容
    github上使用SSH和gitignore
    wordpress 如何设置自定义的首页
    wordpress 删除底部"自豪地采用 WordPress"
    masonry注意事项
    iOS修改工程名
    iOS版本更新在APP中直接访问AppStore
  • 原文地址:https://www.cnblogs.com/ssh-html/p/11726278.html
Copyright © 2011-2022 走看看