javascript 使用sleep函数的常见方法详解


Posted in Javascript onApril 26, 2020

本文实例讲述了javascript 使用sleep函数的常见方法。分享给大家供大家参考,具体如下:

一.什么是sleep函数?

花一点时间来聊一下sleep函数,首先什么是sleep函数?

sleep是一种函数,他的作用是使程序暂停指定的时间,起到延时的效果。

例如:

console.log('1');
sleep(5000);
console.log('2');

控制台输出数字1后会间隔5秒后输出数字2

当然上面的代码是不能执行的,因为js中是没有sleep方法的。

所以这一篇文章主要介绍几种在js中实现sleep的方式。

二.为什么使用sleep?

看到这里有人会问了,为什么要使用sleep,上面的例子我可以使用setTimeout来实现啊?

因为setTimeout是通过回调函数来实现定时任务的,所以在多任务的场景下就会出现回调嵌套:

console.time('runTime:');
setTimeout(function(){
 console.log('1')
 setTimeout(function(){
 console.log('2');
 setTimeout(function(){
  console.log('3');
  console.timeEnd('runTime:');
 }, 2000);
 }, 3000);
}, 2000);
// 1
// 2
// 3
// runTime:: 7013.104ms

上面的方式存在回调嵌套的问题,我们希望有一个优雅的方式来实现上面的例子:

sleep(2000);
console.log('1');
sleep(3000);
console.log('2');
sleep(2000);
console.log('3');
...

三.实现sleep

接下来我们就分别用几种不同的方法来实现下sleep方法

1.基于Date实现

通过死循环来阻止代码执行,同时不停比对是否超时。

function sleep(time){
 var timeStamp = new Date().getTime();
 var endTime = timeStamp + time;
 while(true){
 if (new Date().getTime() > endTime){
  return;
 } 
 }
}
console.time('runTime:');
sleep(2000);
console.log('1');
sleep(3000);
console.log('2');
sleep(2000);
console.log('3');
console.timeEnd('runTime:');
// 1
// 2
// 3
// runTime:: 7004.301ms

缺点:

以上的代码不会让线程休眠,而是通过高负荷计算使cpu无暇处理其他任务。

这样做的缺点是在sleep的过程中其他所有的任务都会被暂停,包括dom的渲染。

所以sleep的过程中程序会处于假死状态,并不会去执行其他任务

2.基于Promise的sleep

为了解决ajax的回调嵌套问题,在jQuery1.8之后支持了Promise。但是单纯的Promise只是将之前的纵向嵌套改为了横向嵌套,

最终结果是下面的代码:

function sleep(time){
 return new Promise(function(resolve){
 setTimeout(resolve, time);
 });
}
console.time('runTime:');
console.log('1');
sleep(1000).then(function(){
 console.log('2');
 sleep(2000).then(function(){
 console.log('3');
 console.timeEnd('runTime:');
 });
});
console.log('a');
// 1
// a
// 2
// 3
// runTime:: 3013.476ms

这其实和之前的setTimeout嵌套没什么区别,也很难看。

我们再次进行优化,使用ES6的Generator函数来改写上面的例子

3.基于Generator函数的sleep

我们对sleep的执行使用Generator函数来执行,并且搭配co来进行自执行。

看代码:

var co = require('co');
 
function sleep(time){
 return new Promise(function(resolve){
 setTimeout(resolve, time);
 });
}
 
var run = function* (){
 console.time('runTime:');
 console.log('1');
 yield sleep(2000);
 console.log('2');
 yield sleep(1000);
 console.log('3'); 
 console.timeEnd('runTime:');
}
 
co(run);
console.log('a');
// 1
// a
// 2
// 3
// runTime:: 3004.935ms

可以看到整体的代码看起来不存在嵌套的关系,还是比较舒服的。

并且执行过程不会发生假死情况,不会阻塞其他任务的执行。

但是多了一个co执行器的引用,所以还是有瑕疵。

当然这不是最终版,因为ES7为我们带来了新的解决方案。

4.基于async函数的sleep

ES7新增了async函数,async函数最大的特点就是自带执行器,所以我们可以不借助co来实现sleep了

看代码:

function sleep(time){
 return new Promise((resolve) => setTimeout(resolve, time));
}
 
async function run(){
 console.time('runTime:');
 console.log('1');
 await sleep(2000);
 console.log('2');
 await sleep(1000);
 console.log('3'); 
 console.timeEnd('runTime:');
}
 
run();
console.log('a');
 
// 1
// a
// 2
// 3
// runTime:: 3009.984ms

效果和之前的一样。

5.使用child_process(子进程)实现sleep函数

前面介绍了几种比较简单的sleep实现,接下来看一个比较难的实现。

原理是将sleep放在子进程中执行,不会影响其他进程,看代码:

var childProcess = require('child_process');
var nodeBin = process.argv[0];
 
function sleep(time) {
 childProcess.execFileSync(nodeBin, ['-e', 'setTimeout(function() {}, ' + time + ');']);
 // childProcess.spawnSync(nodeBin, ['-e', 'setTimeout(function() {}, ' + time + ');']);
}
 
console.time('runTime:');
console.log('1');
sleep(1000);
console.log('2');
sleep(2000);
console.log('3');
console.timeEnd('runTime:');
 
// 1
// 2
// 3
// runTime:: 3579.093ms

以上代码,是通过childProcess对象的execFileSync或者spawnSync创建一个同步进程,

在同步进程中执行定时器,定时器执行完毕后回收进程,程序继续执行。

6.使用npm sleep包

前面的内容都是我们自己实现的,其实npm上已经有很多相关的js包了。

我们来看看他们是怎么实现的,sleep

var sleep = require('sleep');
 
console.log('1');
console.time('runTime:');
sleep.sleep(2); //休眠2秒钟
console.log('2');
sleep.msleep(1000); //休眠1000毫秒
console.log('3');
sleep.usleep(1000000) //休眠1000000微秒 = 1秒
console.log('4');
console.timeEnd('runTime:');
 
// 1
// 2
// 3
// 4
// runTime:: 4014.455ms

很强有没有,sleep包是C++编写,然后扩展到Node来实现sleep函数
也是一个不错的选择。

以上就是sleep的六种简单实现。欢迎大家指出问题,我们一起进步。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JS验证日期的格式YYYY-mm-dd 具体实现
Jun 29 Javascript
使用js实现按钮控制文本框加1减1应用于小时+分钟
Dec 09 Javascript
点击button获取text内容并改变样式的js实现
Sep 09 Javascript
js实现横向伸展开的二级导航菜单代码
Aug 28 Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
Oct 10 Javascript
js利用clipboardData实现截屏粘贴功能
Oct 12 Javascript
Bootstrap复选框和单选按钮美化插件(推荐)
Nov 23 Javascript
jQuery插件FusionCharts实现的3D帕累托图效果示例【附demo源码】
Mar 25 jQuery
jquery Form轻松实现文件上传
May 24 jQuery
ztree加载完成后显示勾选节点的实现代码
Oct 22 Javascript
如何正确理解vue中的key详解
Nov 02 Javascript
vue实现移动端项目多行文本溢出省略
Jul 29 Javascript
基于JavaScript实现十五拼图代码实例
Apr 26 #Javascript
小程序自定义导航栏兼容适配所有机型(附完整案例)
Apr 26 #Javascript
vue 使用 vue-pdf 实现pdf在线预览的示例代码
Apr 26 #Javascript
javascript设计模式 ? 访问者模式原理与用法实例分析
Apr 26 #Javascript
详解关于Vue单元测试的几个坑
Apr 26 #Javascript
es6函数之箭头函数用法实例详解
Apr 25 #Javascript
es6数组之扩展运算符操作实例分析
Apr 25 #Javascript
You might like
php5 apache 2.2 webservice 创建与配置(java)
2011/01/27 PHP
web目录下不应该存在多余的程序(安全考虑)
2012/05/09 PHP
PHP的加密方式及原理
2012/06/14 PHP
php处理文件的小例子(解压缩,删除目录)
2013/02/03 PHP
php实现的IMEI限制的短信验证码发送类
2015/05/05 PHP
PHP将数据导出Excel表中的实例(投机型)
2017/07/31 PHP
xtree.js 代码
2007/03/13 Javascript
JavaScript 变量基础知识
2009/11/07 Javascript
JS中setInterval、setTimeout不能传递带参数的函数的解决方案
2013/04/28 Javascript
js判断鼠标同时离开两个div的思路及代码
2013/05/31 Javascript
Flexigrid在IE下不显示数据的处理的解决方法
2013/10/24 Javascript
JS 在指定数组中随机取出N个不重复的数据
2014/06/10 Javascript
JS实现仿Windows7风格的网页右键菜单效果代码
2015/09/11 Javascript
JS实现部分HTML固定页面顶部随屏滚动效果
2015/12/24 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
2016/11/29 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
2016/12/26 Javascript
利用jquery禁止外层滚动条的滚动
2017/01/05 Javascript
async/await与promise(nodejs中的异步操作问题)
2017/03/03 NodeJs
基于JavaScript实现多级菜单效果
2017/07/25 Javascript
微信小程序wx.request实现后台数据交互功能分析
2017/11/25 Javascript
通过封装scroll.js 获取滚动条的值
2018/07/13 Javascript
详解vue后台系统登录态管理
2019/04/02 Javascript
JavaScript面向对象程序设计中对象的定义和继承详解
2019/07/29 Javascript
原生JS实现多条件筛选
2020/08/19 Javascript
JavaScript实现矩形块大小任意缩放
2020/08/25 Javascript
[46:43]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#2LGD VS MVP.Phx第二局
2016/03/02 DOTA
[54:05]DOTA2-DPC中国联赛定级赛 SAG vs iG BO3第一场 1月9日
2021/03/11 DOTA
对Django外键关系的描述
2019/07/26 Python
Pycharm 2020年最新激活码(亲测有效)
2020/09/18 Python
英国电信商店:BT Shop
2019/12/17 全球购物
华为菲律宾官方网站:HUAWEI Philippines
2021/02/23 全球购物
物业工作计划书
2014/01/10 职场文书
财务出纳岗位职责
2015/03/31 职场文书
小学教研工作总结2015
2015/05/13 职场文书
SQL实现LeetCode(196.删除重复邮箱)
2021/08/07 MySQL
nginx之queue的具体使用
2022/06/28 Servers