【前端面试小册】JS-第29节:实现 sleep

一、核心概念

1.1 什么是 sleep

sleep 函数用于暂停程序执行指定的时间,常用于:

  • 延迟执行
  • 模拟异步操作
  • 控制执行节奏
  • 测试和调试

1.2 应用场景

  • 延迟执行某些操作
  • 控制请求频率
  • 模拟网络延迟
  • 动画控制

二、基础实现

2.1 Promise 版本

const sleep = (time) => {
    return new Promise(resolve => setTimeout(resolve, time));
};

// 使用
sleep(1000).then(() => {
    console.log('1秒后执行');
});

2.2 原理解析

执行流程

graph TD
    A[调用 sleep 1000] --> B[创建 Promise]
    B --> C[设置 setTimeout]
    C --> D[等待 1000ms]
    D --> E[执行 resolve]
    E --> F[Promise 完成]
    F --> G[执行 then 回调]

关键点

  • 使用 Promise 包装 setTimeout
  • setTimeout 的回调中调用 resolve
  • 返回 Promise,支持链式调用

三、增强版本

3.1 支持返回值

const sleep = (time, value) => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(value);
        }, time);
    });
};

// 使用
sleep(1000, '完成').then(result => {
    console.log(result);  // '完成'
});

3.2 支持取消

function sleep(time) {
    let timer = null;
    let rejectFn = null;
    
    const promise = new Promise((resolve, reject) => {
        rejectFn = reject;
        timer = setTimeout(() => {
            resolve();
        }, time);
    });
    
    promise.cancel = () => {
        if (timer) {
            clearTimeout(timer);
            timer = null;
            rejectFn(new Error('Sleep cancelled'));
        }
    };
    
    return promise;
}

// 使用
const sleepPromise = sleep(5000);
sleepPromise.cancel();  // 取消延迟

3.3 支持进度回调

function sleep(time, onProgress) {
    return new Promise((resolve) => {
        const startTime = Date.now();
        const interval = 100;  // 每 100ms 更新一次
        
        const timer = setInterval(() => {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(elapsed / time, 1);
            
            if (onProgress) {
                onProgress(progress);
            }
            
            if (elapsed >= time) {
                clearInterval(timer);
                resolve();
            }
        }, interval);
    });
}

// 使用
sleep(5000, (progress) => {
    console.log(`进度: ${(progress * 100).toFixed(1)}%`);
}).then(() => {
    console.log('完成');
});

四、async/await 使用

4.1 基础用法

const sleep = (time) => {
    return new Promise(resolve => setTimeout(resolve, time));
};

// 使用 async/await
async function demo() {
    console.log('开始');
    await sleep(1000);
    console.log('1秒后');
    await sleep(1000);
    console.log('2秒后');
}

demo();

4.2 循环中使用

async function processItems(items) {
    for (const item of items) {
        await processItem(item);
        await sleep(1000);  // 每个项目处理完后延迟 1 秒
    }
}

4.3 并发控制

async function processWithDelay(items, delay) {
    for (const item of items) {
        await Promise.all([
            processItem(item),
            sleep(delay)
        ]);
    }
}

五、实际应用场景

5.1 延迟执行

async function delayedAction() {
    console.log('准备执行');
    await sleep(2000);
    console.log('2秒后执行');
    // 执行某些操作
    doSomething();
}

5.2 控制请求频率

async function fetchWithDelay(urls) {
    const results = [];
    for (const url of urls) {
        const data = await fetch(url).then(r => r.json());
        results.push(data);
        await sleep(1000);  // 每次请求间隔 1 秒
    }
    return results;
}

5.3 模拟网络延迟

async function mockFetch(url) {
    await sleep(Math.random() * 1000);  // 随机延迟 0-1 秒
    return fetch(url);
}

5.4 动画控制

async function animate(element) {
    for (let i = 0; i <= 100; i++) {
        element.style.opacity = i / 100;
        await sleep(10);  // 每 10ms 更新一次
    }
}

六、不同实现方式对比

6.1 Promise 版本(推荐)

const sleep = (time) => {
    return new Promise(resolve => setTimeout(resolve, time));
};

优点

  • 简洁明了
  • 支持 async/await
  • 符合现代 JavaScript 规范

6.2 回调版本

function sleep(time, callback) {
    setTimeout(callback, time);
}

缺点

  • 不支持 Promise
  • 容易产生回调地狱

6.3 Generator 版本

function* sleepGenerator(time) {
    yield new Promise(resolve => setTimeout(resolve, time));
}

// 使用
const gen = sleepGenerator(1000);
gen.next().value.then(() => {
    console.log('完成');
});

缺点

  • 语法复杂
  • 不常用

七、面试要点总结

核心知识点

  1. Promise 包装:使用 Promise 包装 setTimeout
  2. async/await:支持现代异步语法
  3. 应用场景:延迟执行、控制频率、模拟延迟
  4. 扩展功能:支持取消、进度回调等

常见面试题

Q1: 如何实现 sleep 函数?

答:使用 Promise 包装 setTimeout,在回调中调用 resolve,返回 Promise 支持链式调用和 async/await

Q2: sleep 函数有什么应用场景?

答:

  • 延迟执行某些操作
  • 控制请求频率
  • 模拟网络延迟
  • 动画控制

Q3: 如何实现可取消的 sleep?

答:保存 setTimeout 返回的 timer 和 Promise 的 reject 函数,提供 cancel 方法清除定时器并 reject Promise。

实战建议

  • ✅ 理解 Promise 和 setTimeout 的结合使用
  • ✅ 掌握 async/await 的使用
  • ✅ 根据实际需求扩展功能(取消、进度等)
  • ✅ 注意内存泄漏(及时清理定时器)
#前端面试##银行##滴滴##快手##百度#
前端面试小册 文章被收录于专栏

每天更新3-4节,持续更新中... 目标:50天学完,上岸银行总行!

全部评论

相关推荐

今天 10:09
复旦大学 Java
点赞 评论 收藏
分享
陌夏微秋:一线城市25w左右吧,17×15=255
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务