⚙️ 一、基础实现方案
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()
;- 🚀 场景驱动设计:根据轮询、动画、防抖等需求选择合理延迟时长。