ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

和我一起学习微信小程序(三),封装网络请求

2021-09-21 21:34:12  阅读:126  来源: 互联网

标签:封装 请求 微信 token log res console data wx


任何一款软件,网络请求是必不可少的。这里我提一下,如果你之前有项目,比如web等,必须是前后端分离的架构,否则小程序是无法请求你现有项目的数据,除非你单独另外再为小程序开发一套API。这也是所以为什么现在前后端分离技术那么重要,一个API,可以对应web、小程序、移动端、app等。

我的个人网站,使用node开发的后端API,所以小程序自然也是请求这一套后端程序了。

官方的wx.request函数,不支持promise,始终不明白为什么不支持?非要我们自己封装。

wx.request({
  url: 'example.php', //仅为示例,并非真实的接口地址
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})

当请求成功后,会在回调函数success里执行,如果多层请求,那么就会形成回调地狱,网上封装promise的方法很多,我也是大致借鉴了一点,然后结合自己的项目,进行了一些修改。

首先utits文件夹,新建http.js和refushtoken.js两个文件,前者就是封装wx.request的,后者是我根据自己项目需求,实现刷新token的。

由于我项目的后端API,需要通过header添加token来验证合法性,但此token会保存在服务端的redis数据库中,因为会去比较请求的token是否和redis保存的token一致,所以同一个用户只能同时存在一个token。而且此token有过期时间,所以必须定期刷新token,详见:本网站的架构(三)API接口

另外,正因为同一个用户ID(此用户非微信登录用户,指的是小程序这个客户端本身,相对于后端来说就是一个用户ID)只能保存一个token,那么此时可能很多人跟我想得一样,小程序有数据缓存啊,通过wx.setStorageSync

可以把token缓存到客户端啊,这样每次从缓存读取token就行了啊?

其实完全不行,因为我的token是需要访问后端api来生成的,每次生成的都不同的,如果张三访问后生成的token是‘aaaa’,那么李四访问后生成的token是‘bbbb’,那么后者token就会覆盖前者token,导致张三不能再访问。

所以总结一下,只能把token放在一个公共媒介里,所以用户访问小程序,都是使用这个token。

其实以上这些原理可能比较难理解,其实我网站的前台部分,用.netcore开发的.netcore这个客户端访问后端api的时候,也是相对于一个用户ID,我把生成的token保存在一个静态变量里,那么无论多少网友访问网站,.net都会从静态变量里取出这个token去访问后端。

但是小程序不存在这样的一个公共媒介,后来研究了一下,云数据库可以实现,即把请求来的token都保存在云数据库里,当有网友打开小程序时,直接从云数据库里获得token,即可。

大致的逻辑就是这样,可能并不是一个最好的解决方案,如果大家有什么好的建议,也可以给我留言,以下是代码:

import config from '../config'
import refushtoken from 'refushtoken'
const {
  pubUrl,
  databasetokenID
} = config 
//这是我要请求的数据接口的公共部分
let requestTimes = 0
const http = (options) => {
  requestTimes++
  wx.showLoading({
    title: '加载中',
    mask: true
  })
  return new Promise((resolve, reject) => {
    const db = wx.cloud.database()
    db.collection('localtoken').doc(databasetokenID).get()
      .then((dbres) => {
        // 先从云数据库获取token
        // 之前手动在云数据库中添加了一条token
        // 所以_id是写死在config里了
        const expiresIn = Number.parseInt(dbres.data.expiresIn)
        const createtime = Number.parseInt(dbres.data.createtime)
        const currtime = Math.floor(Date.now() / 1000)
        // console.log(expiresIn + createtime)
        // console.log(currtime + expiresIn)
        if (expiresIn + createtime < currtime + expiresIn / 2) {
          // 如果离过期时间还有一半,则刷新token
          refushtoken()
        }
        return dbres.data.access_token
      })
      .then((token) => {
        // console.log(token)
        wx.request({
          url: pubUrl + options.url,
          method: options.method || 'get',
          data: options.data || {},
          header: {
            'authorization': token
          },
          success(res) {
            if (res.statusCode === 200) {
              //如果状态正确,则返回数据
              resolve(res.data)
            } else if (res.data.code === 10006) {
              refushtoken()
              reject(res)
            } else {
              reject(res)
            }
          },
          fail(error) {
            reject(error)
          },
          complete() {
            requestTimes--
            if (requestTimes == 0) {
              wx.hideLoading({
                success: (res) => {}
              })
            }
          }
        })
      })
      .catch((err) => {
        console.log(err)
      })
  })
}
module.exports = http

当token时间只有一半的时候,或者发生后端特殊错误代码时,就会重新刷新token,refushtoken.js代码如下:

import config from '../config'
const {
  pubUrl,
  apikey,
  userID,
  databasetokenID
} = config 
//这是我要请求的数据接口的公共部分

const refushtoken = () => {
  console.log('开始更新')
  wx.request({
    url: `${pubUrl}/common/token?id=${userID}&key=${apikey}`,
    success(res) {
      const {
        access_token,
        expiresIn,
        createtime
      } = res.data.data
      //console.log(createtime)
      wx.cloud.database().collection('localtoken')
        .doc(databasetokenID)
        .update({
          data: {
            access_token,
            expiresIn,
            createtime
          }
        })
        .then((res) => {
          console.log('更新token成功', res)
        })
        .catch((err) => {
          console.log('更新token失败', err)
        })
    }
  })
}
module.exports = refushtoken

好了,至此符合我项目需求的网络请求,总算封装完毕了,应该还有待优化,不过目前来看,足够使用了。

不过在更新云数据库时,会有权限的问题,官方使用云函数就能完全解决,好吧,接下去让我们改造一下吧,下一节在讲。

第四篇:和我一起学习微信小程序(四),使用云函数完善网络请求

标签:封装,请求,微信,token,log,res,console,data,wx
来源: https://blog.csdn.net/shuanghei/article/details/120405680

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有