UniCloud 是 DCloud 推出的基于 serverless 模式和 js 编程的云开发平台。它让不会后端的前端工程师可以快速完成整栈开发,让开发者专注于业务实现,而无需关心服务器运维等繁琐事务。
降低开发成本
提高开发效率
安全可靠
// 创建云函数示例
'use strict';
exports.main = async (event, context) => {
return {
status: 200,
msg: 'Hello UniCloud'
}
}
在项目根目录创建 uniCloud
目录,包含以下结构:
├── uniCloud
├── cloudfunctions // 云函数目录
└── database // 数据库目录
云函数是运行在云端的 JavaScript 代码。你可以将云函数理解为一个在云端运行的接口,可以在其中编写任意的服务端代码。
// 云函数示例
exports.main = async function(event, context) {
const db = uniCloud.database()
const collection = db.collection('users')
const res = await collection.get()
return res
}
UniCloud 提供了一个 JSON 格式的文档型数据库。它支持在云函数中通过代码操作数据库,也提供了可视化的数据管理界面。
// 插入数据
const db = uniCloud.database()
await db.collection('books').add({
title: '深入浅出 UniCloud',
author: 'DCloud',
price: 99
})
// 查询数据
const res = await db.collection('books')
.where({
price: {
$gt: 50
}
})
.get()
云存储用于存储文件,支持图片、视频、音频等各种类型的文件。
// 上传文件示例
const result = await uniCloud.uploadFile({
filePath: filePath,
cloudPath: 'images/logo.png'
})
// 新增
await db.collection('users').add(data)
// 删除
await db.collection('users').doc(id).remove()
// 修改
await db.collection('users').doc(id).update(data)
// 查询
await db.collection('users').where(condition).get()
const $ = db.command.aggregate
await db.collection('orders')
.aggregate()
.group({
_id: '$status',
total: $.sum('$amount')
})
.end()
// promise方式
uniCloud.callFunction({
name: 'functionName',
data: {
// 参数
}
}).then(res => {
// 处理返回结果
})
// async/await方式
const res = await uniCloud.callFunction({
name: 'functionName',
data: {
// 参数
}
})
// 上传文件
const result = await uniCloud.uploadFile({
filePath: filePath,
cloudPath: 'folder/file.ext'
})
// 下载文件
const result = await uniCloud.downloadFile({
fileID: 'cloud://xxx.jpg'
})
// 删除文件
const result = await uniCloud.deleteFile({
fileList: ['cloud://xxx.jpg']
})
合理设计 Schema
优化查询性能
exports.main = async function(event, context) {
try {
// 业务逻辑
return {
status: 0,
data: result
}
} catch (e) {
return {
status: -1,
msg: e.message
}
}
}
exports.main = async function(event, context) {
const { name, age } = event
if (!name || typeof age !== 'number') {
return {
status: -1,
msg: '参数错误'
}
}
// 继续处理
}
数据验证
敏感数据处理
云函数支持定时触发器功能,可以按照指定的时间规则自动执行:
// 配置示例 cloudfunctions/myFunction/config.json
{
"triggers": [{
"name": "myTrigger",
"type": "timer",
"config": "0 0 2 * * *" // 每天凌晨2点执行
}]
}
将云函数转换为HTTP接口,支持外部系统调用:
// 云函数配置
module.exports = {
path: '/api/test', // 访问路径
method: 'POST', // 请求方法
}
exports.main = async function(event) {
// 函数逻辑
}
支持使用中间件处理通用逻辑:
const middleware = require('uni-middleware')
module.exports = {
middleware: [
async function auth(ctx, next) {
// 身份验证逻辑
const token = ctx.event.headers.token
if (!token) throw new Error('未授权')
await next()
}
]
}
const transaction = await db.startTransaction()
try {
await transaction.collection('accounts').doc('user1').update({
balance: db.command.inc(-100)
})
await transaction.collection('accounts').doc('user2').update({
balance: db.command.inc(100)
})
await transaction.commit()
} catch (err) {
await transaction.rollback()
throw err
}
// 关联查询
const $ = db.command.aggregate
db.collection('orders')
.aggregate()
.lookup({
from: 'users',
localField: 'user_id',
foreignField: '_id',
as: 'userInfo'
})
.match({
status: 'pending',
'userInfo.vip': true
})
.project({
_id: 1,
order_no: 1,
'userInfo.nickname': 1
})
.end()
// 地理位置查询
const _ = db.command
db.collection('stores').where({
location: _.geoNear({
geometry: new db.Geo.Point(113.324520, 23.099994),
maxDistance: 1000,
minDistance: 0
})
}).get()
// 前端代码
async function uploadLargeFile(file) {
const chunkSize = 4 * 1024 * 1024 // 4MB per chunk
const chunks = Math.ceil(file.size / chunkSize)
for(let i = 0; i < chunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize)
await uniCloud.uploadFile({
filePath: chunk,
cloudPath: `chunks/${file.name}_${i}`,
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
console.log(`Chunk ${i + 1}/${chunks}: ${percentCompleted}%`)
}
})
}
}
// 云函数中生成私有文件临时访问链接
exports.main = async function(event) {
const res = await uniCloud.getTempFileURL({
fileList: [{
fileID: 'cloud://xxx.jpg',
maxAge: 3600, // 链接有效期1小时
}]
})
return res.fileList[0].tempFileURL
}
// 在 db_init.json 中配置权限
{
"collection": "articles",
"permission": {
"read": true,
"create": "auth.uid != null",
"update": "doc.author_id == auth.uid",
"delete": "doc.author_id == auth.uid"
}
}
const crypto = require('crypto')
// 加密函数
function encrypt(data, key) {
const cipher = crypto.createCipher('aes-256-gcm', key)
let encrypted = cipher.update(data, 'utf8', 'hex')
encrypted += cipher.final('hex')
return encrypted
}
// 解密函数
function decrypt(encrypted, key) {
const decipher = crypto.createDecipher('aes-256-gcm', key)
let decrypted = decipher.update(encrypted, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}
// 创建索引
db.collection('users').createIndex({
age: 1,
city: 1
}, {
unique: false,
sparse: true
})
// 使用索引查询
db.collection('users')
.where({
age: _.gt(18),
city: 'Shanghai'
})
.get()
// 批量插入
const data = Array.from({length: 1000}, (_, i) => ({
name: `user${i}`,
age: Math.floor(Math.random() * 100)
}))
const batchTimes = Math.ceil(data.length / 100)
for (let i = 0; i < batchTimes; i++) {
await db.collection('users').add(
data.slice(i * 100, (i + 1) * 100)
)
}
// 验证器示例
const validator = {
validateEmail(email) {
const reg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return reg.test(email)
},
validatePhone(phone) {
const reg = /^1[3-9]\d{9}$/
return reg.test(phone)
}
}
// 在云函数中使用
exports.main = async function(event) {
const { email, phone } = event
if (!validator.validateEmail(email)) {
return {
code: -1,
msg: '邮箱格式不正确'
}
}
if (!validator.validatePhone(phone)) {
return {
code: -1,
msg: '手机号格式不正确'
}
}
// 继续处理...
}
// 自定义错误类
class BusinessError extends Error {
constructor(code, message) {
super(message)
this.code = code
}
}
// 统一错误处理
exports.main = async function(event) {
try {
// 业务逻辑
if (condition) {
throw new BusinessError(10001, '业务错误信息')
}
return {
code: 0,
data: result
}
} catch (e) {
if (e instanceof BusinessError) {
return {
code: e.code,
msg: e.message
}
}
console.error(e)
return {
code: -1,
msg: '系统错误'
}
}
}
// 注册
exports.main = async function(event) {
const { username, password, email } = event
// 验证用户名是否存在
const userExist = await db.collection('users')
.where({ username })
.count()
if (userExist.total > 0) {
throw new Error('用户名已存在')
}
// 密码加密
const salt = crypto.randomBytes(16).toString('hex')
const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512').toString('hex')
// 创建用户
const result = await db.collection('users').add({
username,
email,
password: hash,
salt,
created_at: Date.now()
})
return {
code: 0,
data: {
uid: result.id
}
}
}
// 微信小程序登录
exports.main = async function(event) {
const { code } = event
const wxRes = await uniCloud.getWXContext(code)
// 获取用户信息
const userInfo = await db.collection('users')
.where({
openid: wxRes.OPENID
})
.get()
return {
code: 0,
data: userInfo.data[0]
}
}
uni-cloud-router
: 云函数路由管理uni-cloud-database
: 数据库可视化管理eslint-plugin-unicloud
: 代码规范检查// 开启调试模式
const db = uniCloud.database({
debug: true
})
// 查看执行计划
const res = await db.collection('users')
.where({ age: _.gt(18) })
.explain()
console.log(res)
// 在云函数中使用
console.log('普通日志')
console.info('信息日志')
console.warn('警告日志')
console.error('错误日志')
// 查看运行日志
uniCloud.logger.log('详细日志信息')
// uniCloud.config.js
module.exports = {
development: {
functionRoot: './cloudfunctions',
spaceName: 'dev-space'
},
production: {
functionRoot: './cloudfunctions',
spaceName: 'prod-space'
}
}
// 设置告警规则
exports.main = async function(event) {
try {
// 监控指标
const metrics = await uniCloud.metrics.get({
metric: 'function_duration',
period: 300, // 5分钟
})
// 判断是否需要告警
if (metrics.dataPoints[0].value > 1000) {
// 发送告警
await sendAlert('函数执行时间过长')
}
} catch (e) {
console.error(e)
}
}
// 获取广告配置
exports.main = async function(event) {
const ads = await uniCloud.getAdConfig({
adpid: ['your_ad_id']
})
return {
code: 0,
data: ads
}
}
// 微信小程序登录
exports.main = async function(event) {
const { code } = event
const wxRes = await uniCloud.getWXContext(code)
// 获取用户信息
const userInfo = await db.collection('users')
.where({
openid: wxRes.OPENID
})
.get()
return {
code: 0,
data: userInfo.data[0]
}
}
UniCloud 作为一个现代化的云开发平台,为开发者提供了强大且易用的工具和服务。通过本文的学习,你应该已经掌握了:
希望这份教程能帮助你更好地使用 UniCloud 进行开发。如果你在使用过程中遇到任何问题,可以参考官方文档或在社区寻求帮助。