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


猜你喜欢
- 前言Python是一门实现数据可视化很好的语言,他们里面的很多库可以很好的画出图形,形象明了。今天我们就来说说:Pandas数据分析核心支持
- 下午有个朋友问json 数据怎么分页 就捣鼓了一个东东出来下面直接代码:<!DOCTYPE html PUBLIC "-//
- ASP是Web上的客户机/服务器结构的中间层,虽然它使用脚本语言(Java Script,VB Script等)编写,程序代码在服务器上运行
- 导读你真的知道CHAR和VARCHAR类型在存储和读取时的区别吗?还是先抛几条结论吧:1、存储的时候,CHAR总是会补足空格后再存储,不管用
- 本文实例讲述了php将textarea数据提交到mysql出现很多空格的解决方法。分享给大家供大家参考。具体分析如下:有一些朋友可能会发现我
- 一、注释1.#单行注释2."""多行注释"""3.pycharm多行注释快捷键:
- 当我们在Vue.js项目中引用图片时,关于图片路径有以下几种情形:使用一我们在data里面定义好图片路径imgUrl:'../ass
- 目录需求描述:需求解析:解决需求问题解决本人前端菜鸟一名,一直致力于不间断的生产管理后台的bug,并以此自勉自励。近几天接到一个需求,网上也
- 写在前面今天Python笔记的内容是:异常处理一旦Python脚本发生异常,程序需捕获并处理异常。异常处理使得程序能够在处理异常后继续正常执
- 本节主要介绍函数,但是函数是由操作组成的。那么就分为两部,一部分为操作一部分为函数。py世界中的操作。操作if:在学习任何一门语言中,关系i
- 之前一篇文章里提到了利用Cython来编译Python,这次来讲一下如何用Cython给Python写扩展库。两种语言混合编程,其中最重要的
- 本文为大家分享了oracle11g安装图文教程,供大家参考,具体内容如下0、安装环境1、安装包下载1)http://www.oracle.c
- 最近 全栈数据工程师养成攻略 的微信群已经将近500人,开了二群之后为了打通不同微信群之间的消息,花了点时间做了个消息同步机器人,在任意群收
- 一、简介Flask是一个轻量级的基于Python的web框架。本文适合有一定HTML、Python、网络基础的同学阅读。这份文档中的代码使用
- python的列表很重要,学习到后面你会发现使用的地方真的太多了。最近在写一些小项目时经常用到列表,有时其中的方法还会忘哎!所以为了复习写下
- 从一个问题开始最近银行这个事情闹的比较厉害啊,很多储户的钱放在银行,就不翼而飞了,而银行还不管不问,说是用户的责任,打官司,用户还能输了,这
- 本文实例分析了Python二分法搜索算法。分享给大家供大家参考。具体分析如下:今天看书时,书上提到二分法虽然道理简单,大家一听就明白但是真正
- 在Windows平台上,从原来使用C/C++编写原生EXE程序,到使用Python编写一些常用脚本程序,成熟的模块的使用使得编程效率大大提高
- 访问数组元素数组索引等同于访问数组元素。可以通过引用其索引号来访问数组元素。NumPy 数组中的索引以 0 开头,这意味着第一个元素的索引为
- 遇到这么个需求:把图片按照定义的patchsize切块,然后按照z轴顺序叠放小块,如下图(仅考虑灰度图像)图片im,设size为(h,w),