美文网首页华南理工大学创维维生素
百舸争流小程序 总结 (一)

百舸争流小程序 总结 (一)

作者: 藤原拓鞋 | 来源:发表于2020-11-25 17:21 被阅读0次

    开始

    对于创维俱乐部2019-2020完成的小程序,进行总结,主要讲解解决实际问题的过程以及思路。
    努力对代码进行高度封装,保证小程序运行状态监控,与后台交互能够流畅,使得运行逻辑清晰。

    httprequest

    虽然小程序本身对请求有了wx.request()的封装,但我们在项目开发过程中还是对其进行了二次封装,根据后台接口文档,把部分功能进行统一的封装,努力实现接口可扩展性强,对请求的业务分离清晰,保证小程序请求过程能够完整监听,避免网络不畅通,多次点击造成堵塞等。

    首先,根据需要请求不同的数据类型,并且需要加入鉴权的sessionId封装出一个httprequest

    import getSessionId from '../API/getSessionId'
    const baseUrl = require('../config/index').baseUrl    // 服务器基址
    const paramSession = [{},// 选择不同的header
      {'content-type': 'application/json' // 不带上session发送请求
      },
      {'content-type': 'application/x-www-form-urlencoded', // 当发送的参数要求为int时使用
      },
      {'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
      },
      {'content-type': 'application/json', // 当请求需要带上登录状态时使用
      },
      {'content-type': 'multipart/form-data; boundary=XXX', // 上传文件时使用
      }];
    
    /**
     * 
     * @param {*} loading 请求大型数据包标志
     * @param {*} url 请求地址
     * @param {*} sessionChoose 根据数据类型选择content-type
     * @param {*} sessionId 鉴权的sessionId
     * @param {*} params 发送的数据
     * @param {*} method 请求方法
     * @param {*} authCheck 是否需要鉴权的标志
     */
    function httpRequest(loading, url, sessionChoose, sessionId, params, method,authCheck=true) { // 封装统一的请求方法
      if (loading == true) {          // 加载提示
        wx.showToast({
          title: '数据加载中',
          icon: 'loading'
        })
      };
        const realDeal=function() {                     // 实际处理的请求内容
          return new Promise((resolve,reject) => {
          wx.request({
            url: baseUrl + url,
            data: params,
            dataType: "json",
            header: Object.assign(paramSession[sessionChoose],{'Cookie':sessionId||wx.getStorageSync("sessionId")}),
            method: method,
            success: res => {
              console.log(res)
              if (loading == true) {
                wx.hideToast()
              };
              const status=res.statusCode
              const isHttpSuccess=status>=200&&status<300||status===304;
              if(!isHttpSuccess){       // 返回status状态有误
                reject({
                  msg:`httpstatus error: ${status}`,
                  detail:res
                });
                return
              }
              var cookie = res.header["Set-Cookie"] // 获取返回得到的sessionId
              if (cookie != null) {
                wx.setStorageSync("sessionId", res.header["Set-Cookie"]) // 不为空时更新sessionId
              }
              resolve(res);
            },
            fail: err => {
              console.log(err)
              if (loading == true) {
                wx.hideToast()
              }
              reject(err);
            },
            complete: () => {}
          })
        })
      };
      const httpReal=realDeal();            // 实际处理请求内容的promise
      if(authCheck){        // 需要登录状态
        if(getSessionId()){
          return httpReal
        }else{
          wx.showToast({
            title: '请先登录',
            duration: 2000
          });
          return
        }
      }else{                // 公共接口,不需登录
        return httpReal
      }
    }
    
    export default httpRequest
    

    检测登录状态

    由于我们把sessionId储存在了小程序本地缓存中,那就有可能会造成一种情况:后台的登录信息已经过期,但是本地缓存依然存着sessionId,所有需要鉴权的请求都无法成功。

    于是,我们可以封装一个检测sessionId是否过期的方法,若已经过期,则清空相关缓存,提醒用户需要进行登录。

    import httpRequest from '../utils/httpRequest'
    function myCheckSession(callback1,callback2){ // callback2是不存在sessionId时直接运行的回调函数,可选
      let _sessionId = wx.getStorageSync('sessionId')
      let url = '/api/user/showFav/1' // 测试是否sessionId是否仍有效(登录状态有效)
      if(_sessionId){
        return httpRequest(false,url,4,_sessionId,null,'GET',false).then(res => {
          if(res.statusCode == 200){
            wx.setStorageSync('state', 1)
          }
          else{
            wx.removeStorageSync('userInfo')
            wx.removeStorageSync('sessionId')
            wx.setStorageSync('state',0)
            wx.showToast({
              title: res.data.message,
              icon: 'none'
            })
          }
        })
        .then(() =>{
          callback1() // 保证在使用checksession时必须先执行该函数,剩余部分放在回调函数中
        })
      }
      else{
        wx.setStorageSync('state', 0)
        if(callback2){ // 令callback2可选
          callback2() // 未登录时直接运行(sessionId不存在)
        }
      }
    };
    
    export default myCheckSession
    

    接着,我们需要一个动态获取sessionId的方法,当我们的请求需要鉴权的时候,就从本地缓存中取出来加到报文表头。但是,在加入报文之前,还需要通过上方的方法鉴别sessionId是否已经过期。为了避免页面加载时多个请求同时获取sessionId,导致引起多次鉴别sessionId是否过期,我们需要通过一个本地变量记录查询情况。

    import myCheckSession from './myCheckSession'
    let isGettingId=false
    
    function getSessionId(){
      try{
        if(!isGettingId){                             // 避免多次获取
          myCheckSession(function(){
            let state = wx.getStorageSync('state')    // 登录状态,是否过期
            isGettingId=true;
            if(state){
              return wx.getStorageSync('sessionId')
            }else{                                    // 登录过期
              return false
            }
          })
        }
      }catch(err){
        console.log(err);
        return Promise.reject(err)
      }
    }
    
    export default getSessionId
    

    本项目中,我们运用了我们自已的登录系统,但更好的是后台能够调用微信官方的登录鉴权,对其进行封装,获取到我们需要的信息。在以后的项目开发中应该修改这项标准。

    cloudData

    由于一些原因,后面尝试把部分接口分离到了云开发模式,我们对云数据库的操作进行了简单的封装,如下:

    const DB=wx.cloud.database()
    const _=DB.command;
    
    // 连接collection并封装增删改查操作
    class Collection{
      constructor(name){   
        this.collection=DB.collection(name);
      }
    
      add(data){      // 增加一条数据
        return this.collection.add({
          data
        })            // 返回promise
      }
    
      get(where){     // 获取满足条件的数据
        return this.collection.where({
          ...where
        }).get()
      }
    
      getlimit(skipIndex,limitIndex){
        return this.collection.skip(skipIndex).limit(limitIndex).get()
      }
    
      update(where,data){
        return this.collection.where({
          ...where
        }).update({
          data
        })
      }
    
      remove(where){
        return this.collection.where({
          ...where
        }).remove()
      }
    }
    
    module.exports={
      Collection,
      _
    }
    

    以上封装还不完善,以后可以再探索。

    项目中,对于请求基础的封装如上,第一篇总结就先介绍这些。

    相关文章

      网友评论

        本文标题:百舸争流小程序 总结 (一)

        本文链接:https://www.haomeiwen.com/subject/wnpniktx.html