uni-app 不支持过滤器返回 promise,因 vue 3 已移除 filter 且模板不 await 异步函数;应改用 ref + watch 或组合式函数管理异步状态,确保模板只消费确定值。

uni-app 里根本不能用过滤器(filter)返回 Promise,也不该让它参与异步逻辑——这从设计上就是错的路径。
Vue 3 已移除 Vue.filter,uni-app(尤其 Vue3 项目)不支持全局过滤器;即使在 Vue2 兼容模式下,过滤器也只接收同步值、返回同步值,{{ asyncData | myFilter }} 中的 myFilter 拿不到 Promise 的 resolve 结果,只会直接把 Promise 对象转成字符串 [object Promise] 渲染出来。
为什么过滤器里写 async/await 或 return Promise 会失效
过滤器函数本身是纯同步执行的,Vue 模板编译器不会 await 它,也不会为它建立响应式依赖追踪。
- 你写
return new Promise(...)→ 模板拿到的是 Promise 实例,不是最终值 - 你写
async function myFilter(val) { return await api.get(val); }→ 模板渲染时得到的是 pending 状态的 Promise,且无后续更新机制 - 小程序平台连
Vue.filter都不支持,这段代码直接被忽略或报错
想让异步结果进模板,该用 watch + ref 而不是 filter
真正可行的做法是:把异步获取和状态更新拆开,用响应式变量承载最终值,模板只读这个变量。
- 定义
const result = ref(null)和const loading = ref(false) - 用
watch监听原始输入(比如itemId),触发uni.request并赋值给result.value - 模板里写
{{ result.value?.name || '加载中' }},配合v-if="!loading"控制显隐 - 别在
computed里调uni.request—— 计算属性不能有副作用,也不能保证执行时机
需要“格式化+异步取数”混合逻辑?封装成组合式函数
比如一个订单号要查出对应用户昵称,又想复用格式化逻辑,就别塞 filter,改用可复用的逻辑单元:
export function useUserDisplayName() {
const displayName = ref('')
const loading = ref(false)
<p>const fetch = async (orderId) => {
loading.value = true
try {
const res = await uni.request({ url: <code>/api/order/${orderId}/user</code> })
displayName.value = res.data?.nickname || '未知用户'
} catch {
displayName.value = '获取失败'
} finally {
loading.value = false
}
}</p><p>return { displayName, loading, fetch }
}
</p>
在页面中调用 fetch(orderId),模板读 displayName —— 清晰、可控、可测试、跨端一致。
真正卡住人的从来不是“怎么让 filter 支持 Promise”,而是没意识到:模板层只该消费确定值,异步逻辑必须前置到 setup 或逻辑层完成。强行在视图层塞异步,等于把定时炸弹焊死在 UI 上。











