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

作者:李小强 时间:2024-04-22 13:00:08 

本文实例讲述了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函数
也是一个不错的选择。

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

来源:http://www.isjs.cn/?p=1085

标签:javascript,sleep函数
0
投稿

猜你喜欢

  • 原生JS封装_new函数实现new关键字的功能

    2023-09-05 00:44:27
  • php延迟静态绑定实例分析

    2023-11-23 11:44:57
  • Python3 文章标题关键字提取的例子

    2022-02-08 03:45:32
  • Python爬虫小技巧之伪造随机的User-Agent

    2023-11-02 21:32:41
  • python调用windows api锁定计算机示例

    2021-09-08 03:28:38
  • 用一条SQL实现:一行多个字段数据的最大值

    2008-12-31 13:37:00
  • 设计模式学习笔记之 - 简单工厂模式

    2009-03-11 13:38:00
  • javascript中的变量是传值还是传址的?

    2024-04-10 10:52:28
  • 设计的俗化特征

    2010-04-08 16:07:00
  • php开启mysqli扩展之后如何连接数据库

    2023-11-14 17:36:08
  • python正则过滤字母、中文、数字及特殊字符方法详解

    2022-02-20 10:14:47
  • 阿里开源低代码引擎和生态建设实战及思考

    2023-03-30 05:46:43
  • python 提取html文本的方法

    2021-05-27 03:43:46
  • PhpStorm配置debug环境的详细过程

    2023-05-26 20:04:32
  • Python3转换html到pdf的不同解决方案

    2021-10-03 19:50:03
  • 简单实例解释Oracle分页查询

    2023-07-16 00:54:03
  • matplotlib之多边形选区(PolygonSelector)的使用

    2023-12-30 19:33:37
  • Python configparser模块应用过程解析

    2022-08-03 19:56:11
  • 如何获取机器的网络配置属性?

    2009-11-23 20:44:00
  • JS实现运动缓冲效果的封装函数示例

    2023-06-30 14:34:45
  • asp之家 网络编程 m.aspxhome.com