Appearance
实战篇 3-通过小程序云搭建电商后台服务
通过小程序云搭建电商后台服务
上一章已经讲述了小程序云及其使用方法,在这里,本章主要讲解如何通过小程云搭建一个电商的后台服务。本章不会拘泥于每个数据集合的具体字段或是具体代码,而是主要介绍一个电商后台搭建思路,以及前后端的交互方式。正所谓授人以鱼不如授人以渔。
后台服务搭建思路
首先,我们知道一个最简单的后端程序就是,开启一个HTTP
服务,连接上数据库,然后根据收到的请求进行相关操作,例如数据库的增删查改,返回HTML
,返回接口数据之类,如果要外网访问还要部署上线等等。
而用上了小程序云之后,因为云函数这个概念,我们免去了开启服务器和部署的步骤。同时,小程序是天然前后端分离的,也不需要返回HTML
。所以在这种情况下,我们所搭建的后台服务最主要为了实现两个部分的内容,分别是数据库的建立和前后端的数据交互。
数据库建立
数据库建立,指的是数据集合及一些初始数据的创建。在我们搭建的这个 Demo 里,主要是有以下数据集合。
- Information - 首页的资讯数据集,主要是以一个资讯为单位的数据集合,一个资讯可能含有商店图片,商店介绍,商品介绍等,主要作导购作用,点击后引导至相关页面。
- Shop - 商店页的数据集,以商店为单位,一个商店页面里主要是各种楼层数据。
- Commodity - 商品的数据集,显然,一个商品数据自然就是该商品所需要的各种信息。
- Cart - 购物车的数据集,以用户为单位存放购物车数据。
- Order - 订单的数据集,以用户为单位存放订单数据。
- User - 用户信息的数据集,存放用户信息数据。
上面所讲述的 6个数据集,基本就涵盖了一个最简单的电商所需要的各种数据,可以构成一个完整的购物流程。
同时如下图,还可以设置数据集权限。例如将Information
、Shop
、Commodity
设置为所有用户可读、仅管理员可写;将Cart
、Order
、User
改成仅创建者及管理员可读写。通过权限限制,增加了数据集的可靠性。
数据交互
数据集建立起来后,再往里面填充一些假数据,基本的数据就有了,那么在小程序中如何进行数据交互?
如果不是用小程序云,自然是通过request
拉取接口数据,进行展示。而在使用了小程序云的情况下,通过官方提供的sdk
,主要有两种办法进行数据拉取:
- 直接在小程序端操作数据库,获取所需数据,并进行增删查改等操作
- 使用云函数,把数据库的操作放到云端;然后在小程序端调用云函数,达到类似调用接口的效果
第一种方法其实比较适合一些简单的,对数据要求不高,量也不大的小程序。不然在小程序的代码中混合着数据库操作,实践起来不太优雅,也不利于维护。
这里重点说下第二种方法。上篇文章有提到了云函数的概念,这里再回顾一下,所谓云函数,就是将一个函数放在 Node.js(即服务端)环境下运行。因此,我们可以将数据库的操作放到云函数中执行,然后在小程序中调用云函数,达到一种类似调用接口的效果。先看云函数的目录:
├── demo 代码目录
| ├── client 小程序代码目录
| ├── ...
| ├── cloud 小程序云相关代码目录
| ├── functions 云函数相关目录
| ├── shop shop 云函数目录
| ├── index.js 入口函数
| ├── getShop.js getShop.js
| ├── package.json
| ├── ...
| ├── project.config.json 小程序配置文件
| ├── tcb.json 小程序云配置文件
└── README.md readme 文件
这是这个整个 Demo 的目录结构,名字叫 shop 的云函数的具体目录在cloud/functions/shop
下,可以见到有一个入口文件index.js
,还有其它的子函数。下面看具体代码:
// index.js
const app = require('tcb-admin-node') // 官方提供的node-sdk
const { getInformation } = require('./getInformation.js')
const { getShop } = require('./getShop.js')
app.init({
envName: 'taro-ebook-23bbcb',
mpAppId: 'wx9504f077bdc24ea2',
})
exports.main = async (event) => {
const db = app.database()
const { func, data } = event
let res
if (func === 'getInformation') {
res = await getInformation(db)
} else if (func === 'getShop') {
res = await getShop(db, data)
}
return {
data: res
}
}
// 入口函数引用到的getShop函数
// getShop.js
async function getShop (db, venderId) {
const shopColl = db.collection('shop')
const commColl = db.collection('commodity')
const _ = db.command
const res = await shopColl.where({
venderId: _.eq(Number(venderId))
}).get()
const shopData = res.data[0]
const floors = await Promise.all(shopData.floors.map(async (floor) => {
let res = await commColl.where({
skuId: _.in(floor.commodities)
}).get()
floor.commodities = res.data
return floor
}))
shopData.floors = floors
return shopData
}
exports.getShop = getShop
在这个例子中,笔者将一个云函数当成一个模块相关函数的入口,根据函数传入的参数来决定调用哪个函数。而被具体调用的函数,执行的是一些数据的操作,返回数据。也就是说,在这个 Demo 里一个云函数是一个数据模块的入口,里面引用了许多待被调用的具体函数,视入参而定。
以数据模块为单位分割云函数,是笔者觉得比较好的做法。一来云函数不必分割得太细,毕竟每个云函数都是独立部署的,省去了一些繁琐的操作;二来以数据模块为单位,就有点类似我们传统后端的 MVC 模式,易于开发者无缝接入。当然,这只是其中的一种云函数代码组织方式,并不代表就一定要遵循这样的方式,具体情况具体分析,还是要结合业务的实际情况。
而具体到小程序的调用,就更简单了,只是想请求接口的操作改为调用云函数的操作。比如:
// 在小程序端,假如请求接口,我们是这样调用
const res = await wx.request({
url: 'https://api.test.com/shop/xxx',
data: {
a: 'foo',
b: 'bar'
}
})
// 这是调用云函数的情况,调用刚才说到的shop云函数
const res = await wx.cloud.callFunction({
name: 'shop',
data: {
func: 'getShop',
data: {
a: 'foo',
b: 'bar'
}
}
})
可以见到,仅仅是将调用wx.request
改为调用wx.cloud.callFunction
,其它的地方并不需要多改变什么。返回的数据也是可以自己定义的,所以说是达到了调用接口的效果。
不过云函数有一个缺点,就是每次都要上传部署后才能被小程序端调用,调试测试起来略显麻烦。一个比较好的调试方法是添加一个测试函数,在本地环境中使用 Node.js 进行测试。
而官方也在 IDE 中提供了一个测试的方法,同时可以自行定制模板,左边还能看到每次云函数的调用状态。
综上,使用小程序云进行数据交互并不复杂,甚至可以说是简单快捷,极大地加速了开发一整套全栈小程序的效率。
小结
使用小程序云开发电商后台服务与传统的开发方式相比,优势是显而易见的。免去了服务器部署,运维等步骤,为一些不太熟悉后台开发方面的前端开发者提供了一个快速上手,搭建后台服务的方式。有需求的读者可以使用起来。