核心是避免在 yield 扩展完成前访问新属性,因其不保证同步挂载,尤其含异步操作时属性写入存在延迟;需区分 yield 调用与属性实际赋值两个阶段,推荐用 onMounted/nextTick、watch 或封装就绪检查访问器来推迟读取,并避免直接 yield 未 await 的 Promise,宜改用 ref/reactive 显式管理扩展状态。

核心是避免在 yield 扩展完成前就访问新属性——因为 yield 本身不保证同步挂载,尤其当扩展逻辑含异步操作(如 fetch、await、nextTick)时,属性实际写入存在延迟。
确认 yield 扩展是否真正完成
yield 常用于生成器或响应式代理中动态注入属性,但“调用 yield”不等于“属性已写入对象”。需区分两个阶段:
- yield 表达式被调用(如 yield { key: 'name', value: asyncLoad() })
- 对应属性被实际赋值到目标对象(可能发生在微任务、Promise resolve 后)
若在第一阶段后立刻读取 obj.name,而 value 是个 Promise,此时 obj.name 可能仍是 undefined 或 pending 状态。
推迟读取时机,等属性真正可用
不要依赖 yield 调用即刻生效。推荐三种稳妥方式:
- 用 onMounted 或 nextTick 延迟读取:确保响应式系统和 yield 扩展都已完成
- 监听属性变化:对关键字段使用 watch 或 watchEffect,等其非 undefined 时再执行后续逻辑
- 封装带就绪检查的访问器:例如 getProp(obj, 'name', { timeout: 100 }),内部轮询或 await 属性变为有效值
避免在 yield 中混入未等待的异步逻辑
常见错误是在 yield 返回值里直接返回未 await 的 Promise:
- ❌ yield { key: 'data', value: api.fetch() } → api.fetch() 返回 Promise,obj.data 是 Promise 对象,不是数据
- ✅ 改为先 await 再 yield:const data = await api.fetch(); yield { key: 'data', value: data }
若必须保留异步性,yield 应返回一个可等待的包装器(如 ref、computed 或自定义 lazy getter),而非裸 Promise。
用 ref 或 reactive 显式管理扩展状态
将 yield 扩展的结果统一托管到响应式容器中,而非直接挂到原始对象:
- 创建 const extended = ref({})
- yield 完成后执行 extended.value[key] = value
- 所有读取走 extended.value.key,天然具备响应式更新与存在性判断能力
这样既规避了原对象属性挂载时序不可控的问题,也便于做空值防护和 loading 状态联动。

















