编程技术记录

世界你好!

JavaScript如何实现sleep?

一般的,sleep是将当前上下文所在的线程从执行状态转化为挂起状态,直到指定的一段实时时间过去后,再从挂起状态转化为执行状态,在sleep执行结束前,线程不会执行其他任务。

该函数使当前进程从执行状态转化为挂起状态,直到参数seconds所指定的一段实时时间过去后,或者是一个唤醒信号跟踪功能或终止进程功能的信号到来。该挂起时间由于系统的其他调度活动可能会比要求的时间长。

在ES标准中,JavaScript代码的执行环境是一个单线程环境,所以JavaScript如何实现sleep的本质是如何将一个线程阻塞一段时间然后继续工作。

这里的重点是阻塞。所以,使用promisegenerator之类的实现是不满足这个需求的,任务调度机制本质不同,因为promisegenerator的本质是延迟,而不是阻塞。

在不扩展JavaScript语言底层能力的情况下,实现阻塞方式:

  • 计算阻塞
  • IO阻塞

计算阻塞

也就是消耗CPU资源进行阻塞,通常是一段循环计算,在循环期间,JavaScript代码执行线程不会执行其他任务,从而达到模拟sleep的效果

<script type="text/javascript">

// bad implementation
function sleep(milliSeconds){
    var startTime = new Date().getTime(); // get the current time
    while (new Date().getTime() < startTime + milliSeconds); // hog cpu
    }
}
</script>

这种方式在任何标准的ES环境中都可以实现,阻塞和计时在同一个线程中完成。

IO阻塞

也就是消耗IO资源进行阻塞,通常是消耗网络IO,如XMLHttpRequest的同步通信。

<script type="text/javascript">

function sleep(milliSeconds)
{
  var resource;
  var response;
  if(typeof ActiveXObject == 'undefined'){
    resource = new XMLHttpRequest();
  }
  else{
    resource = new ActiveXObject("Microsoft.XMLHTTP");
  }
  try{
    resource.open('GET', 'sleep?milliSeconds=' + milliSeconds, false);
    resource.send(null);
    response = resource.responseText; // JavaScript waits for response
  }
  catch(e){
    alert(e);
  }
}
</script>

这种方式是基于BS模型,Server负责计时,在指定的时间后返回响应,Browser负责阻塞。

引入扩展阻塞

参考 http://devcheater.com/,还可以引入其他语言能力实现sleep,如Java AppletFlash的sleep

© Beli. All Rights Reserved.