编写复杂的JavaScript脚本时,有时会有需求希望脚本能停滞指定的一段时间,类似于 java 中的 Thread.sleep 或者 sh 脚本中的 sleep 命令所实现的效果。

很多语言都有sleep函数,sleep() 方法的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)但是JavaScript中并没有提供类似于 Java 的线程控制的功能, 虽然有 setTimeout 和 setInterval 两个方法可以做一些定时执行控制,但并不能满足所有的要求。

因为setTimeout的本质不是延迟多长时间执行,而是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数,要是当前代码耗时很长,有可能要等很久,所以并没有办法保证回调函数一定会在setTimeout()指定的时间执行。其次setTimeout是通过回调函数来实现定时任务的,所以在多任务的场景下就会出现回调嵌套,代码很不优雅,可读性差等问题。下面介绍JavaScript实现类似sleep的多种方式。

一、基于循环实现sleep

// 使用while循环
function sleep(delay) {var start = new Date().getTime();while (new Date().getTime() - start < delay) {continue;}
}console.log(1, new Date().getTime())  // 1 1631671203441
sleep(2000)
console.log(2, new Date().getTime())  // 2 1631671205441
// 使用for循环
function sleep(delay) {for (var start = Date.now();  Date.now() - start<= delay;);
}console.log(1, new Date().getTime()) // 1 1631671672290
sleep(2000)
console.log(2, new Date().getTime()) // 2 1631671674290

优点:简单粗暴,通俗易懂。

缺点:以上的代码不会让线程休眠,而是通过高负荷计算使cpu无暇处理其他任务。这样做的缺点是在sleep的过程中其他所有的任务都会被暂停,包括dom的渲染。所以sleep的过程中程序会处于假死状态,并不会去执行其他任务

二、基于Promise实现sleep

// 使用promise
function sleep(delay) {return new Promise(resolve =>setTimeout(resolve, delay))
}console.log(1, new Date().getTime())     // 1 1631672405810
sleep(2000).then(() => {console.log(2, new Date().getTime()) // 2 1631672407810
})

优点:这种方式实际上是用了 setTimeout,没有形成进程阻塞,不会造成性能和负载问题。

缺点:虽然不像 callback 套那么多层,但仍不怎么美观,而且当我们需要在某过程中需要停止执行(或者在中途返回了错误的值),还必须得层层判断后跳出,非常麻烦,而且这种异步并不是那么彻底,还是看起来别扭。

三、基于generate实现sleep

// 使用Generator
function* sleep(delay) {yield new Promise(function (resolve, reject) {setTimeout(resolve, delay);})
}console.log(1, new Date().getTime())     // 1 1631673104689
sleep(2000).next().value.then(() => {console.log(2, new Date().getTime()) // 2 1631673106689
})

优点:同 Promise 优点,另外代码就变得非常简单干净

缺点:但不足也很明显,就是每次都要执行 next() 显得很麻烦,虽然有co(第三方包)可以解决,但就多包了一层不好看,错误也必须按co的逻辑来处理不爽。

四、基于 Async/Await 实现sleep

// 使用async/await
function sleep(delay) {return new Promise((resolve) => setTimeout(resolve, delay));
}
async function test() {console.log(1, new Date().getTime()) // 1 1631686674068await sleep(2000);console.log(2, new Date().getTime()) // 2 1631686676068
}
test();

优点:同 Promise 和 Generator 优点。 Async/Await 可以看做是 Generator 的语法糖,Async 和 Await 相较于 * 和 yield 更加语义,另外各个函数都是扁平的,不会产生多余的嵌套,代码更加清爽易读。

缺点: ES7 语法存在兼容性问题,但有 babel 一切兼容性都不是问题

五、使用npm上的node-sleep包

// 引入sleep包
var sleep = require('sleep');
console.log('1');
sleep.sleep(2); //休眠2秒钟
console.log('2');
sleep.msleep(2000); //休眠2000毫秒 = 2秒
console.log('3');
sleep.usleep(2000000) //休眠2000000微秒 = 2秒
console.log('4');

优点:能够实现更加精细的时间精确度,而且看起来就是真的 sleep 函数,清晰直白。

缺点:需要安装这个模块

地址:node-sleep

文章每周持续更新,可以微信搜索「 前端大集锦 」第一时间阅读,回复【视频】【书籍】领取200G视频资料和30本PDF书籍资料

JavaScript实现类似sleep()的多种方式相关推荐

  1. javaScript 合并对象的多种方式

    javaScript 合并对象的多种方式: 1.方式一:Object.assign(obj1, obj2, -) 参数1:obj1 是目标对象 参数2:obj2 是源对象 注意:对象与对象之间,同名属 ...

  2. 多种方式实现文件下载功能

    多种方式实现文件下载功能 (1)使用 NSURLConnection 直接方式 (2)使用 NSURLConnection 代理方式 (3)使用 NSURLsession 直接方式 (4)使用 NSU ...

  3. C++多线程:thread类创建线程的多种方式

    文章目录 描述 函数成员简介 总结 描述 头文件 <thread> 声明方式:std::thread <obj> 简介 线程在构造关联的线程对象时立即开始执行,从提供给作为构造 ...

  4. 《Android深度探索(卷1):HAL与驱动开发》——6.4节使用多种方式测试Linux驱动...

    本节书摘来自异步社区<Android深度探索(卷1):HAL与驱动开发>一书中的第6章,第6.4节使用多种方式测试Linux驱动,作者李宁,更多章节内容可以访问云栖社区"异步社区 ...

  5. 斐波那契数列python递归 0、1、1、2、3_python实现斐波那契数列的多种方式

    正文共: 3269字 8图 预计阅读时间: 9分钟 每日分享 The great pleasure in life is doing what people say you cannot do. 人生 ...

  6. linux删除文件_Linux中删除特殊名称文件的多种方式

    今日分享:我们在肉体的疾病方面花了不少钱,精神的病害方面却没有花什么,现在已经到了时候,我们应该有不平凡的学校.--<瓦尔登湖> 前言 我们都知道,在linux删除一个文件可以使用rm命令 ...

  7. ASP.NET MVC传递Model到视图的多种方式之通用方式的使用

    ASP.NET MVC传递Model到视图的多种方式总结--通用方式的使用 有多种方式可以将数据传递到视图,如下所示: ViewData ViewBag PartialView TempData Vi ...

  8. 【项目】多种方式统一登录入口的设计方案

    在编写项目的时候,通常会遇到很多情况下,需要实现统一登录入口.统一登录入口通常指的是:能够实现手机号.邮箱.用户名等信息登录,且共用一个登录入口. 这种登录方式现在属于一种主流的登录方式,除此之外,移 ...

  9. 工作流模式每个工作流引擎都会支持多种方式的表单。目前大家讨论到的大概有三种。 动态表单 外置表单 普通表单

    工作流模式 抢占 会签 委托代办 催办 自由流 回退 取回 指派 前加签 后加签 改派 驳回 终止 挂起 激活 基本控制流模式 顺序流(Sequence) 并行分叉(Parallel Split) 同 ...

最新文章

  1. Swift初探 1 helloWord
  2. matlab学习札记.20210122
  3. java:多态的实现机制
  4. 联想e480笔记本如何拆屏幕_如何评价 2020 年 10 月 20 日联想发布的小新 Pro14 笔记本?有哪些亮点和槽点?...
  5. 忘记农民就是忘本-农业大健康·万祥军:不要说自己是教授
  6. python编写函数、计算三个数的最大公约数_Python实现利用最大公约数求三个正整数的最小公倍数示例...
  7. lambda中使用filter过滤
  8. 【django之admin,单例模式】
  9. jdk8默认垃圾回收器_JVM系列之经典垃圾回收器(上篇)
  10. Bailian4016 班级排名【稳定排序】
  11. JQuery中如何动态修改input的type属性
  12. MD5加密解密网站测试,MD5加密还安全吗?
  13. shufflenetv1详解
  14. SageMath cputime()
  15. Dota对我来说是什么?
  16. javamail写邮件/邮箱验证报错javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection
  17. 稀疏自动编码(Sparse Autoencoder)
  18. JavaScript:通过点击按钮实现个人信息的录入,进而输出个人信息
  19. 7种方法实现数组去重
  20. 浅谈与时俱进的OS发展史

热门文章

  1. 盘点俄罗斯程序猿写的几款软件,你用过几个?最后1个是我的童年
  2. 压铸新技术和新工艺的发展状况
  3. FPGA学习日记(七)HDMI图像数据传输
  4. 智能电视+android+4.0接收视频,智能电视Android4.0系统魅力小析
  5. 二倍角公式(二倍角公式有哪些)
  6. Linux基础.umask,权限影响,文件类型,/根目录文件,环境变量,alias别名,man手册
  7. android基础笔记1
  8. 怎么用计算机打印收据,用Word轻松制作票据
  9. 【第六章】STM32单片机+NB-IoT模组BC95采集温湿度数据发到电信平台(下)
  10. 互联网公司时尚穿搭指南 1