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 相关文章推荐
jQuery实现个性翻牌效果导航菜单的方法
Mar 09 Javascript
ECMAScript6新增值比较函数Object.is
Jun 12 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
Jan 15 Javascript
利用node.js制作命令行工具方法教程(一)
Jun 22 Javascript
在 Angular中 使用 Lodash 的方法
Feb 11 Javascript
JS实现的DOM插入节点操作示例
Apr 04 Javascript
Vue项目全局配置微信分享思路详解
May 04 Javascript
vue使用原生js实现滚动页面跟踪导航高亮的示例代码
Oct 25 Javascript
详解单页面路由工程使用微信分享及二次分享解决方案
Feb 22 Javascript
vue-cli设置css不生效的解决方法
Feb 07 Javascript
如何使用three.js 制作一个三维的推箱子游戏
Jul 29 Javascript
一小时迅速入门Mybatis之bind与多数据源支持 Java API
Sep 15 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
WAR3重制版DOTA 5V5初体验
2020/04/09 DOTA
GD输出汉字的函数的分析
2006/10/09 PHP
php多功能图片处理类分享(php图片缩放类)
2014/03/14 PHP
php分页原理 分页代码 分页类制作教程
2016/09/23 PHP
datePicker——日期选择控件(with jquery)
2007/02/20 Javascript
javascript TextArea动态显示剩余字符
2008/10/22 Javascript
目前流行的JavaScript库的介绍及对比
2013/09/29 Javascript
JavaScript显示当然日期和时间即年月日星期和时间
2013/10/29 Javascript
js数组的基本操作(很全自己整理的)
2014/10/16 Javascript
node.js中的fs.rename方法使用说明
2014/12/16 Javascript
JavaScript编程中容易出BUG的几点小知识
2015/01/31 Javascript
JS实现根据密码长度显示安全条功能
2017/03/08 Javascript
浅析webpack 如何优雅的使用tree-shaking(摇树优化)
2017/08/16 Javascript
react-native-video实现视频全屏播放的方法
2018/03/19 Javascript
vue-router源码之history类的浅析
2019/05/21 Javascript
javascript实现5秒倒计时并跳转功能
2019/06/20 Javascript
小程序实现搜索框
2020/06/19 Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
2020/04/07 Javascript
python 基础教程之Map使用方法
2017/01/17 Python
Python开启线程,在函数中开线程的实例
2019/02/22 Python
Python Django实现layui风格+django分页功能的例子
2019/08/29 Python
Python爬虫实现使用beautifulSoup4爬取名言网功能案例
2019/09/15 Python
简单了解django处理跨域请求最佳解决方案
2020/03/25 Python
解决matplotlib.pyplot在Jupyter notebook中不显示图像问题
2020/04/22 Python
python db类用法说明
2020/07/07 Python
详解python安装matplotlib库三种失败情况
2020/07/28 Python
欧洲最大的品牌水上运动服装和设备在线零售商:Wuituit Outlet
2018/05/05 全球购物
最新大学毕业求职简历的自我评价
2013/10/18 职场文书
致100米运动员广播稿
2014/02/14 职场文书
党员干部公开承诺书
2014/03/26 职场文书
优秀团员自我评价范文
2014/04/23 职场文书
巴西世界杯32强口号
2014/06/05 职场文书
个人授权委托书范文
2014/09/21 职场文书
小学教师师德师风自我评价
2015/03/04 职场文书
超市督导岗位职责
2015/04/10 职场文书
普希金的诗歌赏析(3首)
2019/08/20 职场文书