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

开始

对于创维俱乐部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,
  _
}

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

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • A类问题(技术) 1. 请谈谈微信小程序作用? project.config.json 项目配置文件,用得最多的就...
    七月鎏金阅读 1,678评论 0 3
  • 写在前面 微信小程序出来也蛮久了,经过了市场的考验,已经站稳脚跟,融入到了各行各业,市场需求激增打来的是开发人员的...
    月梦佳期阅读 1,717评论 1 1
  • 网络请求 wx.request(Object object) 发起网络请求,最终发送给服务器的数据是 String...
    花霏花阅读 873评论 0 3
  • 软件框架 定义 一个软件是由其中各个软件模块组成的,每一个模块都有特定的功能,模块与模块之间通过相互配合来完成软件...
    jxvl假装阅读 585评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,579评论 16 22