第九节 高频代码题-实现Sleep函数(异步控制)
⚙️ 一、基础实现方案
1. Promise + setTimeout 标准实现
function sleep(ms: number): Promise<void> {return new Promise(resolve => setTimeout(resolve, ms));
}
原理:
- 返回一个
Promise
对象,在指定毫秒(ms
)后调用resolve
结束等待。 - 通过
setTimeout
实现异步调度,避免阻塞主线程。
2. 使用示例(async/await)
async function demo() {console.log("开始等待");await sleep(2000); // 暂停 2 秒console.log("等待结束");
}
demo();
输出:
开始等待
(2秒后)
等待结束
🚀 二、工程化增强方案
1. 支持返回值传递
通过泛型扩展 sleep
功能,实现延迟后返回数据:
function sleep<T>(ms: number, value?: T): Promise<T | void> {return new Promise(resolve => setTimeout(() => resolve(value), ms));
}// 使用:延迟后返回字符串
async function fetchWithDelay() {const data = await sleep(1000, "Hello, World!");console.log(data); // 输出 "Hello, World!"
}
2. 集成错误处理
支持延迟中抛出异常:
function sleep(ms: number, shouldReject = false): Promise<void> {return new Promise((resolve, reject) => {setTimeout(() => {shouldReject ? reject(new Error("Sleep interrupted")) : resolve();}, ms);});
}// 使用:模拟失败场景
async function riskyOperation() {try {await sleep(1000, true);} catch (error) {console.error(error.message); // 输出 "Sleep interrupted"}
}
⚠️ 三、关键注意事项
-
非阻塞特性
sleep
通过事件循环实现延迟,不会阻塞同步代码:console.log("Start"); sleep(2000).then(() => console.log("Delayed")); console.log("End"); // 输出:Start → End →(2秒后)→ Delayed
-
禁止同步滥用
在同步函数中调用await sleep()
会导致整个函数暂停,但若在非async
函数中使用会报错:function syncFunction() {await sleep(1000); // ❌ 语法错误:await 仅在 async 函数中有效 }
-
替代方案对比
方法 适用场景 缺点 setTimeout
简单回调场景 嵌套易导致回调地狱 Promise + sleep
现代异步流程(推荐) 需配合 async/await 第三方库(如 bluebird
)复杂任务调度 增加依赖体积
💡 四、典型应用场景
-
接口轮询控制
async function pollAPI() {while (true) {const data = await fetchData();if (data.status === "ready") break;await sleep(5000); // 每 5 秒轮询一次} }
-
用户操作防抖
let searchTimer: number; function onSearchInput(query: string) {clearTimeout(searchTimer);searchTimer = setTimeout(async () => {await sleep(300); // 延迟 300ms 后执行搜索runSearch(query);}, 300); }
-
动画序列控制
async function playAnimations() {animateElement1();await sleep(1000);animateElement2();await sleep(500);animateElement3(); }
🛠️ 五、扩展:Node.js 环境优化
在 Node.js 中可复用 setTimeout
,或使用 setImmediate
实现微秒级延迟:
import { setTimeout } from "timers/promises"; // Node.js 16+async function nodeSleep(ms: number) {await setTimeout(ms);
}
最佳实践总结:
- ✅ 优先 Promise 方案:保持代码简洁与现代异步规范兼容;
- ⚠️ 避免同步思维:理解事件循环机制,禁止在非 async 函数中调用
await sleep()
;- 🚀 场景驱动设计:根据轮询、动画、防抖等需求选择合理延迟时长。