JavaScript实现Sleep函数

许多编程语言都提供了一个名为sleep的函数,它能够暂时停止程序的执行,持续一定的时间。然而,JavaScript并没有直接包含这样的内置功能。因此,在这篇文章中,我们将深入探讨在JavaScript中实现延迟的各种方法,同时充分考虑到这门语言的异步特性。 

 示例

console.log('vue')
sleep(1000)
console.log('react')

sleep函数的作用,就是在打印了vue之后再过一秒才会打印react,要实现这种功能的sleep函数,有几种方式。

do..wile循环

通过模仿传统的sleep行为实现暂停效果:

/**
 * 该函数接受一个以毫秒为单位的参数,表示延迟的时间长度。
 * 它通过不断检查当前时间与开始时间之间的差值,直到达到指定的延迟时间。
 * @param {number} ms - 延迟的时间长度,以毫秒为单位。
 */
function sleep(ms) {
  // 获取当前时间的戳
  const date = Date.now();
  // 初始化当前时间为 null
  let currentDate = null;
  // 开始一个循环,直到延迟时间结束
  do {
    // 获取当前时间的戳
    currentDate = Date.now();
    // 检查当前时间与开始时间之差是否小于延迟时间
  } while (currentDate - date < ms);
}

虽然这种写法可以实现我们想要的效果,但是这种同步的实现方式会阻塞代码的执行,这在JavaScript这种异步语言中通常是不推荐的,因为它会影响到代码的响应性和性能。在阻塞期间,JavaScript引擎无法执行其他任务,这可能导致资源的浪费。而且这种实现依赖于循环检查,它的延迟时间可能不会非常精确,尤其是在高负载的环境下

setTimeout

在JavaScript中,setTimeout是一个全局函数,用于在将来的某个时间点执行一段代码。它常常用于实现延迟执行、定时任务、轮询等场景。setTimeout函数接收两个参数:一个回调函数和一个延迟时间(单位为毫秒)。在延迟时间到达之前,回调函数不会执行。一旦延迟时间到达,回调函数就会被添加到事件队列中,并在当前线程的下一个空闲时间点执行。

 console.log('vue');
 setTimeout(() => {
     console.log('pause');
 }, 1000);
 console.log('react');

上面的代码的执行结果你认为会是vue、pause、react这个顺序打印么?事实并非如此,这是打印结果:

setTimeout函数并没有暂时程序的执行,浏览器瞬间打印出了vue和react,过了一秒后打印了pause。因为setTimeout是一个异步函数,意味着它不会阻塞代码的执行。

 console.log('vue');
 setTimeout(() => {
     console.log('react');
 }, 1000);

这样能实现在打印vue后过一秒再打印react。这种非阻塞性的方式简洁明了,它的实施过程不需要深入理解Promise或async/await的复杂概念。然而,这种方法并不适合处理那些异步逻辑较为复杂的任务,并且它缺少对错误的处理机制。通常,在你需要执行一系列按时间顺序排列的简单任务时,可以采用这种方式。这些任务之间不需要复杂的同步或通信。

Promise和setTimeout

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

console.log('vue');
sleep(2000).then(() => { console.log('react'); });

这种方式不会阻塞操作,而且它提供了对异步流程的精细控制。不过需要对Promise有深入的理解。当Promises链变得过长时,可能会引起一些混乱。这种技术在你需要更细致地管理时间和异步任务时尤为有用。

async/await与Promise

虽然Promise+setTimeout的写法已经可以实现我们想要的效果,但是很不美观,因此我们可以用async ... await来优化一下:

 function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
 }

 async function logFunction() {
   console.log('vue');
   await sleep(1000);
   console.log('react');
 }

这种语法非常直观,便于理解,而且不会阻塞代码的执行。不过要求你必须要熟悉async/await和Promise的概念。此外,你通常需要在模块的外部对函数进行一层“包装”。如果你正在处理多个异步任务,我强烈推荐使用这种方法,因为它是最现代和最干净的解决方案。

总结

在异步编程领域,选择合适的工具对于编写高效、可维护的代码至关重要。对于简单的延迟操作,setTimeout提供了直接且易于理解的解决方案。然而,当涉及到更复杂的异步流程,如顺序执行或错误处理时,Promise和async/await则成为了更强大的工具。尽管它们可能需要更多的学习和理解,但它们提供了更加结构化和可读的代码,从而提高了代码质量和开发效率。因此,根据具体需求和场景,选择最合适的异步处理方法对于成为一名高效的开发者至关重要。

你可能感兴趣的:(JavaScript进阶之路,前端,javascript,vue.js,性能优化,html5,typescript,node.js)