如何使用 async/await 实现条件等待

如何使用 async/await 实现条件等待
最新回答
々苏晓瑾丶訫冷控

2024-04-11 06:18:47

使用 async/await 实现条件等待的核心方法是构建一个异步忙等待函数(如 busyWait),通过周期性检查条件并结合 Promise 和 setTimeout 实现暂停,直到条件满足后继续执行。 以下是具体实现步骤、示例代码及注意事项:

1. 实现 busyWait 函数

定义一个异步函数,接受条件测试函数和可选的延迟时间(默认 500ms),在循环中检查条件,不满足时暂停执行。

async function busyWait(test, delayMs = 500) { while (!test()) { await new Promise(resolve => setTimeout(resolve, delayMs)); }}
  • 参数说明

    test:返回布尔值的函数,用于判断条件是否满足。

    delayMs:每次检查失败后等待的毫秒数(默认 500ms)。

  • 实现原理

    while (!test()):循环检查条件,若不满足则执行内部逻辑。

    await new Promise(...):通过 setTimeout 创建延迟的 Promise,await 暂停执行直到 Promise 完成(即延迟结束),避免阻塞主线程。

2. 示例代码:等待变量变化

以下示例演示等待变量 a 的值从 'hello' 变为 'world':

let a = 'hello';// 模拟异步操作:2秒后更新变量setTimeout(() => { a = 'world'; console.log(`[${new Date().toLocaleTimeString()}] a 更新为: ${a}`);}, 2000);// 使用 busyWait 等待条件(async () => { console.log(`[${new Date().toLocaleTimeString()}] 等待 a === 'world'...`); await busyWait(() => a === 'world'); console.log(`[${new Date().toLocaleTimeString()}] 条件满足!a = ${a}`);})();
  • 运行结果

    输出初始值 a = 'hello'。

    进入 busyWait 循环,每 500ms 检查一次 a === 'world'。

    2 秒后 a 更新为 'world',下一次检查时条件满足,循环终止。

    输出 条件满足!a = world。

3. 关键注意事项
  • 避免死循环:确保条件最终会变为 true,否则 busyWait 会无限等待。
  • 选择合适的 delayMs

    过小:频繁检查增加 CPU 负担(如 10ms)。

    过大:条件满足后响应延迟(如 5000ms)。

    建议:根据场景调整(UI 交互通常 100-1000ms)。

  • 替代方案

    事件驱动:如监听 DOM 变化(MutationObserver)或数据加载事件。

    Promise 链:直接等待另一个异步操作完成(如 fetch)。

    状态管理库:React 的 useEffect + Redux/Vuex 监听状态变化。

  • 超时机制:可扩展 busyWait 添加 timeoutMs 参数,超时后抛出错误。
4. 扩展:带超时的 busyWaitasync function busyWait(test, delayMs = 500, timeoutMs) { const startTime = Date.now(); while (!test()) { if (timeoutMs && Date.now() - startTime > timeoutMs) { throw new Error('条件等待超时'); } await new Promise(resolve => setTimeout(resolve, delayMs)); }}// 使用示例(async () => { try { await busyWait(() => a === 'world', 500, 3000); // 最多等待3秒 } catch (e) { console.error(e.message); }})();5. 总结
  • 适用场景:简单条件等待(如等待变量变化、API 响应状态更新)。
  • 优势:代码简洁,易于理解,适合轻量级需求。
  • 局限:轮询机制可能消耗资源,复杂场景建议使用事件驱动或响应式编程。

通过合理设计 delayMs 和超时机制,async/await 条件等待能高效解决异步编程中的状态同步问题。