跳到主要内容

Sleep 函数

JavaScript 中实现延迟执行的方法。

基础实现

// 返回 Promise 的 sleep 函数
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

// 使用(配合 async/await)
async function demo() {
console.log('开始');
await sleep(1000); // 等待 1 秒
console.log('1 秒后执行');
}

demo();

使用示例

顺序执行

async function sequential() {
console.log('第一步');
await sleep(1000);
console.log('第二步');
await sleep(1000);
console.log('第三步');
}

sequential();
// 输出间隔各 1 秒

重试机制

async function retry(fn, maxRetries = 3, delay = 1000) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
console.log(`${i + 1} 次失败,${delay}ms 后重试...`);
await sleep(delay);
}
}
throw new Error('重试失败');
}

// 使用
const fetchData = async () => {
const response = await fetch('/api/data');
if (!response.ok) throw new Error('网络错误');
return response.json();
};

retry(fetchData, 3, 2000)
.then(data => console.log('成功:', data))
.catch(err => console.error('最终失败:', err));

轮询

async function poll(fn, interval = 1000, maxAttempts = 10) {
for (let i = 0; i < maxAttempts; i++) {
const result = await fn();
if (result) return result;
await sleep(interval);
}
throw new Error('轮询超时');
}

// 使用:等待页面元素出现
async function waitForElement(selector, timeout = 5000) {
const start = Date.now();

while (Date.now() - start < timeout) {
const element = document.querySelector(selector);
if (element) return element;
await sleep(100);
}

throw new Error(`元素 ${selector} 未找到`);
}

// 使用
const button = await waitForElement('#submit-btn');
button.click();

延迟执行任务

// 延迟显示消息
async function showMessage(message, delay = 2000) {
const el = document.createElement('div');
el.textContent = message;
document.body.appendChild(el);

await sleep(delay);

el.remove();
}

showMessage('操作成功!');

动画序列

async function animateSequence() {
const box = document.querySelector('.box');

box.style.transform = 'translateX(0)';
await sleep(500);

box.style.transform = 'translateX(100px)';
await sleep(500);

box.style.transform = 'translateX(200px)';
await sleep(500);

box.style.transform = 'translateX(0)';
}

animateSequence();

带进度回调

function sleepWithProgress(ms, onProgress) {
return new Promise(resolve => {
const start = Date.now();
const interval = 50;

const timer = setInterval(() => {
const elapsed = Date.now() - start;
const progress = Math.min(elapsed / ms, 1);

if (onProgress) {
onProgress(progress);
}

if (elapsed >= ms) {
clearInterval(timer);
resolve();
}
}, interval);
});
}

// 使用
await sleepWithProgress(3000, progress => {
console.log(`进度:${(progress * 100).toFixed(0)}%`);
});

取消延迟

function cancellableSleep(ms) {
let resolved = false;
let timer = null;

const promise = new Promise(resolve => {
timer = setTimeout(() => {
resolved = true;
resolve();
}, ms);
});

return {
promise,
cancel: () => {
if (!resolved && timer) {
clearTimeout(timer);
}
}
};
}

// 使用
const { promise, cancel } = cancellableSleep(5000);

// 2 秒后取消
setTimeout(cancel, 2000);

await promise; // 如果取消则不会执行

注意事项

// 1. Sleep 不会阻塞其他代码执行
async function demo() {
console.log('A');
await sleep(1000);
console.log('B');
}
console.log('C');
// 输出顺序:C, A, B

// 2. 在循环中使用
for (let i = 0; i < 5; i++) {
console.log(i);
await sleep(1000); // 每次间隔 1 秒
}

// 3. 不要滥用
// 如果是为了等待异步操作完成,应该直接 await 该操作
// Sleep 主要用于控制执行节奏