上篇讲完ArkUI-X跨端适配后台问得最多的是“本地Demo跑通了怎么对接真实的后台数据总不能一直用模拟的商品列表吧” 之前我们的电商Demo所有数据都存在本地重启App就清零也不支持多用户下单。今天就用华为云Serverless服务实现端云一体化不用自己买服务器、搭数据库2小时把本地Demo变成能上线的线上应用。所有步骤适配API23踩了8个官方文档没写的坑最终实现商品数据云端存储、多用户共享、下单数据实时同步赶稿可直接复用。一、前言为什么端云一体化是电商App的必选项之前的系列内容里我们用AppStorage存临时数据、PersistentStorage做本地持久化、DistributedDataObject实现跨设备同步但这些方案都有局限数据只存在用户本地换个手机就丢失不支持多用户A用户加购的商品B用户看不到无法做真实下单所有交互都是模拟的。端云一体化的核心价值就是用Serverless无服务架构把后端能力封装成API前端直接调用不用关心服务器运维、数据库扩容、安全防护这些复杂问题。对中小团队和个人开发者来说能节省70%的后端开发成本上线周期从1个月压缩到2天。端云一体化能力对比实测结论维度纯本地存储端云一体化Serverless数据持久化仅本地换设备丢失云端永久存储跨设备同步多用户支持不支持数据隔离支持用户数据互不影响运维成本无无云厂商托管开发难度低仅前端低前端少量云函数适用场景Demo演示真实上线应用二、核心概念辨析官方没讲透的边界很多新手会把云存储和之前的分布式文件服务DFS搞混先明确三个核心服务的定位2.1 云函数Cloud Functions定位运行在云端的代码片段处理业务逻辑比如下单校验、价格计算。类比相当于后端的Controller层前端通过HTTP请求调用不用关心服务器部署。适用场景用户登录校验、下单逻辑处理、数据聚合计算。2.2 云数据库Cloud DB定位云端NoSQL数据库存储结构化数据比如商品信息、订单记录。类比相当于后端的Model层比本地的PersistentStorage容量更大、支持多用户访问。适用场景商品列表存储、用户信息管理、订单数据持久化。2.3 云存储Cloud Storage定位云端文件存储服务存储非结构化数据比如商品图片、用户头像。类比相当于分布式的DFS但数据存在云端所有用户可访问支持CDN加速。适用场景商品图片存储、视频资源托管、用户上传文件管理。核心认知云数据库存“数据记录”云存储存“文件本身”云函数处理“业务逻辑”三者配合实现完整的后端能力。之前的DFS是跨设备共享本地文件云存储是跨用户共享云端文件这是两者的本质区别。三、代码实现API23 电商端云实战3.1 开通云服务5分钟搞定登录华为云开发者联盟控制台进入AppGallery ConnectAGC创建项目选择HarmonyOS平台开通云函数、云数据库、云存储三个服务在“我的项目-项目设置-常规”里复制应用APP ID后续初始化SDK用。3.2 初始化云SDKUIAbility中完成在EntryAbility.ts中初始化云服务能力确保所有页面都能调用import { abilityAccessCtrl, AbilityConstant, UIAbility, Want } from kit.AbilityKit import { window } from kit.ArkUI import { cloud } from hw-agconnect/cloud export default class EntryAbility extends UIAbility { async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promisevoid { console.log(EntryAbility onCreate) // 1. 初始化云SDK核心 try { // 从AGC下载的配置文件放到entry/src/main/resources/rawfile目录下 const context this.context await cloud.initialize(context, agconnect-services.json) console.log(云SDK初始化成功) } catch (err) { console.error(云SDK初始化失败, err.message) } // 2. 后续初始化逻辑权限申请、分布式服务等... } // 其他生命周期方法省略... }3.3 封装云请求工具类工程化必备创建entry/src/main/ets/common/CloudUtil.ets统一封装云函数、云数据库的调用逻辑避免重复代码import { cloud } from hw-agconnect/cloud import { BusinessError } from kit.BasicServicesKit /** * 云端服务工具类 * 统一封装云函数、云数据库的调用逻辑 */ export class CloudUtil { private static readonly DB_NAME shop-db // 云数据库名称 private static readonly GOODS_COLLECTION goods // 商品集合 private static readonly ORDER_COLLECTION orders // 订单集合 /** * 调用云函数 * param funcName 云函数名称 * param params 函数参数 * returns 函数执行结果 */ static async callFunction(funcName: string, params?: Recordstring, Object): Promiseany { try { const result await cloud.callFunction({ name: funcName, params: params || {} }) console.log(云函数${funcName}调用成功, result) return result.result } catch (err) { const e err as BusinessError console.error(云函数${funcName}调用失败, e.message) throw e } } /** * 查询云数据库 * param collectionName 集合名称 * param query 查询条件 * returns 查询结果列表 */ static async queryDatabase(collectionName: string, query?: any): Promiseany[] { try { const db cloud.database({ name: this.DB_NAME }) const collection db.collection(collectionName) const snapshot await collection.query(query || {}).get() console.log(云数据库${collectionName}查询成功共${snapshot.length}条数据) return snapshot } catch (err) { const e err as BusinessError console.error(云数据库${collectionName}查询失败, e.message) throw e } } /** * 插入云数据库 * param collectionName 集合名称 * param data 插入数据 * returns 插入结果 */ static async insertDatabase(collectionName: string, data: any): Promiseany { try { const db cloud.database({ name: this.DB_NAME }) const collection db.collection(collectionName) const result await collection.add(data) console.log(云数据库${collectionName}插入成功, result) return result } catch (err) { const e err as BusinessError console.error(云数据库${collectionName}插入失败, e.message) throw e } } }3.4 改造商品列表页从云端加载数据修改之前的Index.ets把本地模拟数据替换为云端查询import { router } from kit.ArkUI import { CloudUtil } from ../common/CloudUtil import { GoodsBean } from ./GoodsItem Entry Component struct Index { State goodsList: GoodsBean[] [] // 商品列表从云端加载 State isLoading: boolean true // 加载状态 aboutToAppear(): void { // 页面显示时加载云端商品数据 this.loadGoodsFromCloud() } /** * 从云端加载商品列表 */ async loadGoodsFromCloud(): Promisevoid { this.isLoading true try { // 调用云数据库查询商品列表按价格升序排序 const result await CloudUtil.queryDatabase(goods, { orderBy: { price: asc } // 按价格升序 }) // 转换为本地GoodsBean对象 this.goodsList result.map((item: any) ({ id: item.id, title: item.title, price: item.price })) console.log(云端商品数据加载成功共, this.goodsList.length, 条) } catch (err) { console.error(云端商品数据加载失败, err) // 降级方案加载本地模拟数据 this.goodsList [ { id: 1, title: 【API23新特性】HarmonyOS 6.1 定制款商品, price: 5999 }, { id: 2, title: 华为Mate 60 Pro 先锋计划, price: 6999 } ] } finally { this.isLoading false } } // 列表渲染逻辑复用之前的LazyForEach代码无需修改 build() { Column() { // 标题 Text(云端商品列表) .fontSize(24) .fontWeight(FontWeight.Bold) .margin({ top: 20, bottom: 20 }) // 加载状态 if (this.isLoading) { LoadingProgress() .width(60) .height(60) .margin({ top: 100 }) } else { // 商品列表复用之前的LazyForEach代码 List() { LazyForEach(this.goodsList, (item: GoodsBean) { ListItem() { GoodsItem({ goods: item }) } }, (item: GoodsBean) item.id.toString()) } .width(100%) .layoutWeight(1) } } .width(100%) .height(100%) .backgroundColor(#f0f0f0) } }3.5 实现下单功能云函数处理业务逻辑创建云函数在AGC控制台创建名为create-order的云函数代码如下Node.js环境const cloud require(hw-agconnect/cloud); exports.handler async (event, context) { const db cloud.database(); const orderCollection db.collection(orders); // 1. 校验参数 const { userId, goodsId, count } event.body; if (!userId || !goodsId || !count) { return { code: 400, message: 参数缺失 }; } // 2. 查询商品价格 const goods await db.collection(goods).doc(goodsId).get(); if (!goods) { return { code: 404, message: 商品不存在 }; } // 3. 计算总价 const totalPrice goods.price * count; // 4. 插入订单数据 const order { userId, goodsId, count, totalPrice, createTime: new Date().getTime(), status: pending // 待支付 }; const result await orderCollection.add(order); // 5. 返回结果 return { code: 200, message: 下单成功, data: { orderId: result.id, totalPrice } }; };在商品详情页调用下单云函数修改DetailPage.ets点击“加入购物车”时调用云函数// DetailPage.ets 新增下单逻辑 async addToCart(): Promisevoid { if (this.goodsId 0) return try { // 模拟用户ID实际项目中从登录状态获取 const userId test-user-001 // 调用云函数创建订单 const result await CloudUtil.callFunction(create-order, { userId: userId, goodsId: this.goodsId, count: 1 // 默认加购1件 }) if (result.code 200) { promptAction.showToast({ message: 下单成功订单号${result.data.orderId} }) router.back() } else { promptAction.showToast({ message: result.message }) } } catch (err) { console.error(下单失败, err) promptAction.showToast({ message: 下单失败请重试 }) } }四、踩坑记录官方文档没写的8个细节云函数超时时间默认3秒如果下单逻辑复杂比如调用第三方支付需要到AGC控制台把云函数的超时时间调到10秒以上否则会报timeout错误。云数据库查询默认返回20条如果需要查询更多数据要加limit参数比如query({ limit: 100 })最多支持1000条。云存储跨域问题如果在Web端访问云存储的图片需要在AGC控制台配置跨域规则允许你的域名访问否则会报CORS错误。模拟器调试云函数本地可以用agc-cloud-functions-emulator工具模拟云函数执行不用每次都部署到云端调试效率提升80%。云数据库权限配置默认云数据库是私有的需要配置安全规则允许已登录用户读写否则会报permission denied错误。规则示例allow read,write: if request.auth ! null。云函数冷启动问题长时间未调用的云函数会有冷启动延迟1-3秒可以在AGC控制台开启“定时触发”功能每隔5分钟调用一次云函数避免冷启动。本地配置文件路径agconnect-services.json必须放到entry/src/main/resources/rawfile目录下否则SDK初始化时会找不到配置文件。降级方案必须做云端服务可能出现网络波动所有云请求都要加try-catch失败时降级到本地模拟数据保证App基本功能可用。