uniapp云函数无法实时推送异步结果,必须通过uni.getpushclientid获取并缓存cid后,由云函数调用unipush.sendmessage下发消息,客户端用uni.onpush监听,配合force_notification和payload实现伪实时通知。

UniApp 无法直接“实时推送云函数的异步结果”,因为 uniCloud 云函数本身是无状态、短生命周期的 HTTP 或事件触发式执行单元,它不维持长连接,也不支持服务端主动向客户端“推”数据。所谓“实时推送结果”,实际是客户端主动轮询、监听启动参数、或借助推送通道间接实现——本质是“伪实时”,必须绕过“函数返回即结束”这个硬限制。
uni.getPushClientId() 拿不到 cid 就别谈后续推送
所有基于 uniPush 的服务端推送,前提都是客户端已成功获取并持久化 cid(push_clientid)。常见失败现象包括:
-
getPushClientId:fail register fail:manifest.json 中未开启 push 能力,或厂商配置(如华为appid、小米appkey)有一处大小写/空格/前缀错误 - 返回
cid为空字符串或null:真机调试没用「自定义基座」,默认基座不含任何厂商 SDK - Android 12+ 权限缺失:manifest.json 缺少
"android.permission.POST_NOTIFICATIONS",连权限弹窗都不触发
务必在 onLaunch 中调用 uni.getPushClientId,且 success 回调里立即缓存到 uni.setStorageSync 或 uniCloud.callFunction 同步到 opendb-device 表——别等用户登录后再取,冷启动时就该有。
云函数不能 return 后再“补发”,得靠 uniPush 主动投递
你写一个耗时操作(比如生成报表、处理图片),想“做完立刻通知用户”,不能指望云函数执行完再把结果塞进响应体——客户端早已断开连接。正确路径是:
- 云函数收到请求后,立即返回一个临时
request_id给前端,并异步启动后台任务(可用setTimeout或另起轻量云函数) - 后台任务完成后,调用
uniPush.sendMessage,把结果通过payload字段下发到该用户的push_clientid - 客户端用
uni.onPush监听,收到后解析payload并更新 UI 或弹 toast
关键点:force_notification: true 确保 Android/iOS 都显示通知栏;payload 必须是合法 JSON 字符串(不是对象),否则部分通道会丢弃。
uni.onPush 和 onNotificationClick 的触发时机很具体
这两个 API 不是“随时都能监听到”,它们只在特定上下文生效:
-
uni.onPush:仅当 App 在前台运行时能收到透传消息(force_notification: false时),且必须在onLaunch或onShow后注册才有效 -
uni.onNotificationClick:只在用户点击通知栏消息时触发,且仅在 App 已启动(热启动或冷启动)后才能捕获——冷启动时,参数会附在uni.getLaunchOptionsSync().notification里 - 不要在组件
onLoad里注册监听器,应统一放在App.vue的onLaunch+onShow中,避免重复绑定
如果用户点了通知但没跳转页面,大概率是 onNotificationClick 注册太晚,或者 uni.navigateTo 被拦截(比如当前是 tabBar 页面,需用 switchTab)。
离线消息存活时间(off_line_ttl)和 channel_id 容易被忽略
厂商通道对离线消息有严格时效和分类限制,配置错会导致“明明发了却收不到”:
- 小米、OPPO、vivo 的
channel_id必须在各自开发者平台创建并填入options对象对应字段,漏填或填错值,Android 8.0+ 就不显示通知 -
off_line_ttl默认是 3600 秒(1小时),但 OPPO/VIVO 实际支持最长 86400 秒(24小时),华为则要求 ≤ 259200(3天);设太短,用户关机几小时就丢消息 - 鸿蒙、华为、荣耀通道必须传
category,值为"DEVICE_REMINDER"等系统类目,否则按营销消息限频,一天最多推 3 条
这些参数不是可选的“锦上添花”,而是厂商审核和通道路由的硬性准入条件——哪怕 cid 正确、签名有效,channel_id 缺失照样静默失败。











