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

 0 0条评论

第三篇中,封装了网络请求,咋看一下貌似还可以,实际运用中发生很多问题。

一,代码不够优雅。

二,之前的版本是每次有请求后去判断token是否过期,但是取的token还是之前数据库里的token,如果长时间小程序没人访问的话,这个数据库保存的token其实已经过期了。

那么只能再修改一下代码,思路就是,每一次的网络请求,都要去判断一下token是否过期,如果已经过期,则从后端重新获取token,然后更新数据库,并且返回最新的token。

好了,让我们开始修改代码吧。

先新建一个文件夹,cloud,两个云函数


然后在配置文件中加上以下代码

  "cloudfunctionRoot": "cloud/",

那么,cloud文件夹的边上,就会出现一朵云。


然后新建getdbtoken,和refushtoken两个云函数


getdbtoken函数功能主要是获取当前云数据库里保存的token。

云函数需要接受一个参数databasetokenID,然后通过id查找数据库对应的token。

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const {
    databasetokenID
  } = event
  return new Promise((resolve, reject) => {
    cloud.database().collection('localtoken').doc(databasetokenID).get()
      .then(res => {
        resolve(res.data)
      })
      .catch(err => {
        reject(err)
      })
  })
}

http.js就是封装了网络请求的,思路就是,先去getdbtoken获取token,然后根据当前时间和过期时间判断,是否已经快过期了,如果快过期,则执行refushtoken云函数返回使用返回的token发送网络请求,如果没有过期,则使用原来数据库中保存的token发送网络请求,代码如下:

import config from '../config'
const {
  pubUrl,
  apikey,
  userID,
  databasetokenID
} = config
//这是我要请求的数据接口的公共部分
let requestTimes = 0
const http = (options) => {
  requestTimes++
  wx.showLoading({
    title: '加载中',
    mask: true
  })
  return new Promise((resolve, reject) => {
    wx.cloud.callFunction({
        name: 'getdbtoken',
        data: {
          databasetokenID
        }
      })
      .then(dbtoken => {
        let access_token = dbtoken.result.access_token
        const expiresIn = Number.parseInt(dbtoken.result.expiresIn)
        const createtime = Number.parseInt(dbtoken.result.createtime)
        const currtime = Math.floor(Date.now() / 1000)
        console.log(createtime)
        console.log(expiresIn + createtime)
        console.log(currtime + expiresIn / 2)
        //expiresIn + createtime < currtime + expiresIn / 2
        if (expiresIn + createtime < currtime + expiresIn / 2) {
          console.log('刷新token咯')
          wx.cloud.callFunction({
            name: 'refushtoken',
            data: {
              pubUrl,
              apikey,
              userID,
              databasetokenID
            }
          }).then(res => {
            console.log('云函数来的token', res.result)
            resolve(httprequest(options,res.result) )
          })
        } else {
          resolve(httprequest(options,access_token))
        }

      })
      .catch((err) => {
        console.log('错误', err)
      })
  })
}

function httprequest(options,access_token) {
  return new Promise((resolve, reject) => {
    console.log('request里的token',access_token)
    wx.request({
      url: pubUrl + options.url,
      method: options.method || 'get',
      data: options.data || {},
      header: {
        'authorization': access_token
      },
      success(res) {
        if (res.statusCode === 200) {
          //如果状态正确,则返回数据
          resolve(res.data)
        } 
        else {
          reject(res)
        }
      },
      fail(error) {
        reject(error)
      },
      complete() {
        requestTimes--
        if (requestTimes == 0) {
          wx.hideLoading({
            success: (res) => {}
          })
        }
      }
    })
  })
}

module.exports = http

核心部分就是refushtoken这个云函数,云函数也是异步返回数据的,如果想阻塞当前进程,直到有返回值再进行下一步,同样的需要进行promise包装,代码如下:

// 云函数入口文件
const cloud = require('wx-server-sdk')
const request = require('request-promise')
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
  const {
    pubUrl,
    apikey,
    userID,
    databasetokenID
  } = event
  const url = `${pubUrl}/common/token?id=${userID}&key=${apikey}`

  return new Promise((resolve, reject) => {
    request({
      url,
      json: true
    }).then(res => {
      const {
        createtime,
        expiresIn,
        access_token
      } = res.data
      cloud.database().collection('localtoken').doc(databasetokenID)
        .update({
          data: {
            access_token,
            createtime,
            expiresIn
          }
        }).then(() => {
          resolve(access_token)
        })
        .catch(err=>{
          reject(err)
        })
    })
  })
}

至此总算完成代码

第五篇:和我一起学习微信小程序(五),首页数据调用api



本文作者:双黑

版权声明:本站文章欢迎链接分享,禁止全文转载!

游客