云环境搭建
项目初始化
使用框架mpx(类vue语法开发小程序的框架)
## 全局安装脚手架
npm i -g @mpxjs/cli
## 初始化项目
mpx create mpx-cloud-function-demo
选择云函数相关的配置
mpx云函数说明:mpxjs.cn/guide/advan…
配置云函数文件目录并暴露main函数
配置云函数和小程序的指定目录
生成的小程序的代码和云函数的代码均需要再project.config.json中指明,才能被微信开发平台的对指定目录的读取
暴露main函数
const application = require('./framework/core/application.js')
exports.main = async (event, context) => {
return await application.app(event, context)
}
在云函数的的出口文件index.js中暴露main方法(因为是node环境,所以使用export方法),此处,我是将index.js仅仅作为暴露的出口,将核心逻辑写在application.js的方法中(具体代码如下:)
const cloudBase = require('../cloud/cloud_base.js')
const appUtil = require('./app_util.js')
const routes = require('../../config/route.js')
const config = require('../../config/config.js')
const dayjs = require('dayjs')
const splitLine = '▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦▦'
async function app(event) {
const cloud = cloudBase.getCloud()
const wxContext = cloud.getWXContext()
let r = ''
try {
// note: 错误排查,如果没有路由,可以理解为https的url
if (!event.route) {
console.error(`Route Not Defined: ${event}`)
return appUtil.handlerSvrErr()
}
r = event.route.toLowerCase()
// note: 如果没有/需要直接报错
if (!r.includes('/')) {
console.error(`Route Format error[${r}]: ${event}`)
return appUtil.handlerSvrErr()
}
// note: 如果没有得到配置的对应value值
if (!routes[r]) {
console.error(`Route [${r}] Is Not Exist: ${event}`)
return appUtil.handlerSvrErr()
}
// note: 进入正常的逻辑处理中去,根据云函数的请求来获取具体的模块,用配置的路由的value值去做相关的请求处理,使用@将controller层和每一层的执行方法定义出来
const routesArr = routes[r].split('@')
let [controllerName, actionName] = routesArr
const time = dayjs().format('YYYY/MM/DD HH:mm:ss')
const timeTicks = dayjs().valueOf()
const openId = wxContext.OPENID
// note: 将controller层和执行模块进行记录,以及用户的openid收集
console.log(splitLine)
console.log(`time: ${time} \n ENV: ${config.CLOUD_ID} \n Controller: ${controllerName}\n Action: ${actionName}\n OPENID: ${openId}`)
// note: 引入对应模块的逻辑controller的名称
controllerName = controllerName.toLowerCase().trim()
// note: 获取相关的controller并实例化
const ControllerClass = require(`project/controller/${controllerName}.js`)
const controller = new ControllerClass(r, openId, event)
// note: 初始化接口逻辑处理
if (controller && controller.initSetUp) {
await controller.initSetUp()
}
let result = await controller[actionName]()
// note: 返回值处理,判断是否需要包装成小程序的规范处理
if (isOther) {
return result
} else {
result = result ? appUtil.handlerData(result, r) : appUtil.handlerSucc(r)
}
// note: 记录每个接口调用耗时和具体请求和响应的时间
const endTime = dayjs().format('YYYY/MM/DD HH:mm:ss')
const endTimeTicks = dayjs().valueOf() - timeTicks
console.log(`endTime: ${endTime} \n endTimeTicks: ${endTimeTicks}`, result)
console.log(splitLine)
return result
} catch (ex) {
const log = cloud.logger()
const time = dayjs().format('YYYY/MM/DD HH:mm:ss')
console.error(`time: ${time} \n MSG: ${ex.message} \n CODE: ${ex.code}`)
// node: 系统级错误定位调试
if (ex.name !== 'AppError') throw ex
console.log(splitLine)
if (ex.name === 'AppError') {
log.warn({
route: r,
errCode: ex.code,
errMsg: ex.message
})
return appUtil.handlerAppErr(ex.message, ex.code)
} else {
log.error({
route: r,
errCode: ex.code,
errMsg: ex.message,
errStack: ex.stack
})
return appUtil.handlerSvrErr(ex)
}
}
}
module.exports = {
app
}
小坑:此处遇到过一个问题:在本地调试和正式环境的表现不一致,其原因是本地的node版本和正式环境的node版本不一致
上传函数并新建函数
上传云函数到微信云开发平台
选择模块example上传到云端
如果目录下存在package.json,云端自动检测并安装相关依赖
在云开发平台创建对应的云函数
注意这个地方云函数名称要与上传时候的模块的目录名称一样
实现数据的crud
初始化云函数配置
const config = require('../../config/config.js')
const getCloud = () => {
const cloud = require('wx-server-sdk')
cloud.init({
env: config.CLOUD_ID // note: 下图对应的环境ID
})
return cloud
}
module.exports = {
getCloud
}
不同层的数据处理及数据流向
分层调用
比较通用的后端分层
数据库调用
数据连接及修改
const cloudBase = require('../cloud/cloud_base.js')
const cloud = cloudBase.getCloud()
const db = cloud.database()
const collectionName = 'demo_test_data'
// note: 添加数据
db.collection(collectionName).add({
data
})
// note: 删除数据
db.collection(collectionName).where({
filed: ''
}).remove()
// note: 更新数据
db.collection(collectionName).where({
filed: ''
}).update({
data
})
// note: 数据查询
db.collection(collectionName).get()
| 关系型 | 文档型 |
|---|---|
| 数据库 database | 数据库 database |
| 表 table | 集合 collection |
| 行 row | 记录 record / doc |
| 列 column | 字段 field |
云开发提供的json库本质就是MongoDB的文档型数据库,均为非关系型数据库
文件上传
async uploadImg() {
const chooseResult = await wx.chooseImage()
if (chooseResult?.tempFilePaths?.length) {
const res = await wx.cloud.uploadFile({
cloudPath: guid(),
filePath: chooseResult.tempFilePaths[0]
})
if (res?.fileID) {
await this.callFunction({
route: 'demo/filenameupload',
params: {
fileID: res.fileID
}
})
this.getImgList()
}
}
},
callFunction({ route = 'demo/filelist', params = {} } = {}) {
return new Promise((resolve, reject) => {
wx.cloud.callFunction({
name: 'example', // note: 想要调用对应的模块名称
data: { // note: 上传的值,对应到云函数侧可以被event取到其所有值
route,
params
}
}).then(res => {
resolve(res.result)
}).catch(err => {
reject(err)
})
})
}
前端调用
云函数调用初始化
wx.cloud.init({
env: 'env-id',
traceUser: true
})
一般在app.mpx中完成
调用数据示例
callFunction({ route = 'demo/get', params = {} } = {}) {
return new Promise((resolve, reject) => {
wx.cloud.callFunction({
name: 'example', // note: 想要调用对应的模块名称
data: { // note: 上传的值,对应到云函数侧可以被event取到其所有值
route,
params
}
}).then(res => {
resolve(res.result)
}).catch(err => {
reject(err)
})
})
}
总结
demo完成过程中遇到的问题
- 本地调试和线上的node版本不一致问题
云开发的优劣
优势(特点)
- 坡度小:无需搭建服务器和数据库,开发体验对前端极其友好
- 高效便捷:在微信体系内的鉴权简单,获取微信相关信息容易
- 成本低:开发成本和维护成本都比较低,上线也十分方便
不足
- 数据读取慢:数据调用的速度略慢,详细的数据对比还需数据统计(可能是买的套餐问题导致)
- 无法友好的处理数据量大的情况
- 无法友好打通微信生态和非微信应用之间的数据交互(虽然现在官方已经可以提供web sdk,但调用起来并没有http那么方便
云开发的使用场景
适用场景
- 制作demo:产品原型阶段能力调用测试
- 小型应用:预约系统
- 个人创业小项目:配置较少,核心功能较少,微信端的应用
- 毕业设计,完整的数据流,且需要的时间很少,学习成本也相对较小
不建议使用场景
- 强依赖后台配置的应用
- 大型应用
- 需要跨端的应用
基于以上优劣,个人不建议单独花费大量时间去学习
todelist
- 消息推送(需要验证token的服务器)
- 支付相关(需要企业商户、个体经商户)
- 云开发数据库与web应用的调用问题(调研实现方式)
- 日志收集能力(方便排错)
demo视觉
备注:可主要关注数据效果,前端效果暂时没优化