欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

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


这篇文章主要介绍了javascript 使用sleep函数的常见方法,结合实例形式分析总结了javascript sleep函数的功能、常见使用方法与操作注意事项,需要的朋友可以参考下    

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

一.什么是sleep函数?    

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

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

例如:

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

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

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

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

二.为什么使用sleep?    

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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                                    

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

1
2
3
4
5
6
7
sleep(2000);                                    
console.log('1');                                    
sleep(3000);                                    
console.log('2');                                    
sleep(2000);                                    
console.log('3');                                    
...                                    

三.实现sleep    

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

1.基于Date实现    

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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只是将之前的纵向嵌套改为了横向嵌套,

最终结果是下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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来进行自执行。

看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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了

看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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放在子进程中执行,不会影响其他进程,看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.jb51.net/code/HtmlJsRun测试上述代码运行效果。

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

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

您可能感兴趣的文章:    


来自 https://www.jb51.net/article/185441.htm


普通分类: