
在无法使用 await 的同步执行环境(如 requestAnimationFrame 循环)中,可通过预设状态变量(如 done 和 result)监听 Promise 完成状态,并在每次循环中安全读取其结果。
在无法使用 `await` 的同步执行环境(如 `requestanimationframe` 循环)中,可通过预设状态变量(如 `done` 和 `result`)监听 promise 完成状态,并在每次循环中安全读取其结果。
在 Web 动画或高频同步更新场景(如游戏循环、实时可视化渲染)中,我们常需在 requestAnimationFrame 回调中反复执行逻辑,但该回调是纯同步上下文,不支持 await。若某项异步操作(如 fetch)的结果需在后续帧中复用,就必须以非阻塞、无竞态的方式“轮询”其完成状态与值。
核心思路是:将 Promise 的生命周期状态显式映射为可同步访问的变量。推荐做法如下:
- 声明状态标识与缓存容器:定义布尔标志(如 isResolved)标记是否已完成;定义变量(如 data)存储最终结果;
- 在 .then() 中一次性写入状态:利用 Promise 的不可变性,确保 then 回调仅执行一次,安全更新状态;
- 在同步循环中直接条件判断与读取:无需额外开销,零成本检查状态并使用结果。
示例代码(生产就绪版):
let promise = fetchSomething(); // 例如:fetch('/api/data').then(r => r.json())
let isResolved = false;
let data = null;
// 仅执行一次,安全捕获结果与错误
promise
.then(result => {
isResolved = true;
data = result;
})
.catch(error => {
isResolved = true; // 也标记为“已 settled”,避免无限等待
console.warn('Promise rejected:', error);
// 可选:设置默认值或空数据,保持 drawThing 接口稳定
data = null;
});
function updater() {
drawSomething();
if (isResolved) {
drawThing(data); // 此处 data 已确定存在(或为 null/undefined)
}
requestAnimationFrame(updater);
}
updater();
⚠️ 注意事项:
- 不要使用 promise.status 或类似非标准属性——原生 Promise 没有同步检查状态的 API,Promise.prototype.finally() 或 .then() 是唯一可靠入口;
- 避免在 updater 中重复调用 .then(),否则每次循环都会创建新微任务,造成内存与性能浪费;
- 若 Promise 可能被拒绝,务必添加 .catch() 处理,否则未捕获错误会静默失败,且 isResolved 将永不置为 true;
- 如需支持多次重试或动态 Promise 切换,可封装为可重置的状态管理器(如 const useAsyncValue = () => ({ resolve, isResolved, value })),但基础场景上述模式已足够简洁高效。
此方案零依赖、无第三方库、符合 Promise 规范,是同步驱动场景下对接异步数据最轻量、最可控的实践方式。










