由js实现延时函数sleep延伸出来的一点想法

刚下班,累了,但是这个问题其实困扰我很多年了,今晚又偶然想起,决定把这个问题拿出来说一说,但是我就不打算给出具体代码了,因为,凡是优雅而彻底的方法他如果不是原生支持的那就一定是复杂的实现,我现在没有精力去写那么复杂的东西。但是,提供一个思路,有兴趣的朋友自己去实现也可以。

 

首先我们来看看为什么js原生不支持像python的time.sleep()这样的方法,因为js是单线程的嘛,你一sleep他就阻塞了。当然,js也给出了一些代替的机制,那就是setTimeout和setInterval,还有写游戏的人都喜欢的requestAnimationFrame,这三者都不是真正意义上的time.sleep,而是定时任务,在任务执行完毕之后去执行下一个函数/事件。

我们可以这样写:

function1();

setTimeout(function2,1000)

但是如果有多层,就会变成:

function1();

setTimeout(function(){

function2();

setTimeout(function3,1000);

},1000);

其实如果需求不是很复杂,用这种看起来很蛋疼的写法也是可以的。如果想做得精细一点,可以自己封装一个函数,伪代码如下:

var clock = new Clock();

clock.add(function1,0)

clock.add(function2,1000)

clock.add(function3,2000)

clock.run()

至于怎么实现这个很简单的clock,其实就是结束事件链式调用而已,就不赘述了。这个方案比上一个优雅一些,但是依然和python java这种自带sleep函数的语言差距明显。

 

如果可以使用外部力量(也就是不纯靠js)的话,其实也有一些解决方案,比如说使用flash、javalet的sleep方法,或者用ajax配合后端的php/java/python/golang/c++等等做个异步,都可以,这个网上都有教程,我也懒得展开,但终究觉得怪怪的。知乎上还有人扯远扯到了fibjs,它底层相当于自己重构了嘛,当然可以随便sleep了,顺便一提,这是个很好的后端协程应用开发框架,值得安利一下,有兴趣的话建议百度一下做了解。

 

有的人可能会说可以用es6的async和promise大法来解决,嗯,像这样:

function sleep(millisecond) {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve()
            }, millisecond)
        })
    }
    async function test() {
        const start = new Date().getTime();
       console.log("执行开始",start);
       await sleep(3000);
       console.log("执行结束",new Date().getTime() - start)
   }
    test();

如果是只面向现代浏览器的话,其实这样写无可厚非了,甚至可以说是最佳解决方案了,但是如果要兼容那些破烂老旧浏览器,这招是不是还是要凉凉?

那要不,这样?

function sleep(delay) {
    var start = new Date().getTime();
    while (new Date().getTime() < start + delay)
        ;
}

这样在火狐谷歌等浏览器需要大概跑掉20-60%的CPU,如果是老爷机,可能会让你卡到怀疑人生,如果是IE8这种石器时代的浏览器,想都不要想,直接崩给你看。当然,部分网站为了省事确实是用这种代码写的。毕竟,燃烧用户的CPU关我开发者什么事?

但是,我总觉得,不够优雅,以上这些实现,除了使用es6语法的高端实现以外,基本上都是比较折衷的方案。

说到底,还是js这种语言先天性的机制不支持time.sleep()这种语法吧。

等等,你说先天性?

那如果在解析器层面上让他支持呢?

转念一想,可行啊,应该是可行的,不,肯定是可行的,既然有大佬可以用js写系统,用js写lua、python脚本解析器,那当然也可以用js写js代码解析器了。

而且,我们需要的不复杂,

只需要将形如:

fun1()

sleep(500)

fun2()

这样的代码翻译成:

var clock = new Clock();

clock.add(fun1,0)

clock.add(fun2,500)

clock.run()

这样的代码不就可以了?关于这个clock还可以有更优雅的实现,读者朋友自己想一下都可以任意扩展。 

聪明如你肯定一下子就想到了eval()和正则表达式了,如果追求比较简单,是可以将整个业务逻辑的js读成大字符串,再对这个大字符串进行处理后,再用eval()函数去跑这个大字符串的。

但是,js本身的函数稍微复杂了一些

有这样的:fun1()

有这样的:(function(){fun2()})()

有这样的:fun3(function(){ fun4() })

。。。

还要考虑嵌套的问题、在循环体之间的sleep问题等等,用简单的正则表达式去匹配出来,怕不是难以搞定而且容易出bug。

那么,换个思路,直接来解析js,像个真正的解析器一样,把文本解析成AST,再对AST进行系列加工和封装。

可参考:https://zhuanlan.zhihu.com/p/34191831

这个东西搞起来绝对是个大工程,精力有限,我没办法搞了。但是至少留一个思路给有心人吧。解析器本身不需要太过复杂,只要对解析出来的执行语句进行稍微包装,最终还是变成字符串交由我们伟大的eval函数去执行。性能上可能会稍损,但影响不会很严重。我认为这才是彻底的、优雅的、终极的解决js不支持time.sleep的方法。

通过对js的二次解析,还可以赋予js更多的语法和扩展性,甚至将js彻底变成另一门语言。我现在没精力做这么大的事情了。思路留给大家吧。

如果实现了,那就真的是赋予js新的活力了,绝不只是解决一个比较无关疼痒的sleep这么简单。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C语言中,可以使用延时函数sleep实现延时操作。引用中提到,sleep函数的参数是以秒为单位的整数。比如,如果想要程序暂停1秒钟,则可以使用sleep(1)。在Linux下,函数名为sleep而不是Sleep,且参数的单位是秒而不是毫秒。需要在代码中包含头文件unistd.h。而在Windows操作系统中,可以使用Sleep函数来实现延时操作,参数是以毫秒为单位的整数。使用示例代码如下所示:[2] #include <windows.h> int main(){ int a; a = 1000; // 延时1秒(1000毫秒) Sleep(a); // 使用Sleep函数进行延时 return 0; } 需要注意的是,Sleep函数是Windows操作系统特有的函数,在Linux下不能直接使用。在Linux下,可以使用usleep函数来实现延时操作,参数是以微秒为单位的整数。比如,如果想要程序暂停500毫秒,则可以使用usleep(500000)。需要在代码中包含头文件unistd.h。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【c++】6.延时函数sleep()、usleep()、delay()和计算程序运行时间的函数clock()](https://blog.csdn.net/u011754972/article/details/115904323)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [linux和windows下,C/C++开发的延时函数sleep函数](https://blog.csdn.net/knaha/article/details/104277727)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值