通过setTimeout理解js异步原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tomhs3000/article/details/80061501

在上一篇的文章中介绍了js异步原理,有的小伙伴可能还有些云里雾里,在本篇文章中将以新手很容易用错的setTimeout为例来解释js的异步原理。

首先我们看一个例子

<script>
  console.log(1);
  setTimeout(function(){
    console.log(2);
  },500);
  console.log(3);
  // 运行结果
  // 1
  // 3
  // 2
</script>

这里通过setTimeout延迟500毫秒执行,所以结果是1,3,2。这看起来明明就是异步操作啊,为什么说是同步呢?我们接着看下一个例子。

<script>
  var date = new Date();
  console.log('first time: ' + date.getTime());
  setTimeout(function(){
      var date1 = new Date();
      console.log('second time: ' + date1.getTime() );
      console.log( date1.getTime() - date.getTime() );
  },1000);
  for(var i=0; i < 10000 ; i++){
      console.log(1);
  }
  // 运行结果
  // first time: 1524540272462
  // (10000)1
  // second time: 1524540274346
  // 1884
</script>

神奇的事情出现了,假设js是异步,那么结果应该是这样的:

// first time: 1524540272462

//(x)1

// second time: 1524540273462

// 1000

//(10000-x)1

扫描二维码关注公众号,回复: 3798280 查看本文章

x为一秒内打印的1的数量。

但是实际结果settimeout并非是1000毫秒后执行的,而是1884毫秒。其原因是js是单线程,在打印完first time: 1524540272462后settimeout内的操作进入了“任务队列”,而1000毫秒到了以后,因为当前js正在执行打印1的操作,故js会在1打印完之后,才将settimeout内操作压进执行栈里。所以实际上我们看到的结果1884毫秒的原因就在于次。

这个例子说明js仍旧是单线程而非多线程,在同一时间内js只能做一件事情。

下面我们通过下面的简单例子也能够看出js是单线程的。

<script>
  console.log('1');
  setTimeout(function(){
      console.log('2');
  },10);
  while(true){};
  // 运行结果
  // 1
</script>

浏览器打印出1后就卡死了,并没有打印出2来。因为执行栈必须把当前任务完成,任务队列里的操作才能进入执行栈。而执行栈内的操作是死循环,所以浏览器卡死,2也不会被打印出来。



下面来看一种特殊情况,当setTimeout的时间为0的时候是不是立即执行的。

  console.log(1);
  setTimeout(function(){
      console.log(2);
  },0);
  console.log(3);
  // 运行结果
  // 1
  // 3
  // 2

结果证明即便延迟设为0,也不是立即执行的。因为 setTimeout有一个最小执行时间,当指定的时间小于该时间时,浏览器会用最小允许的时间作为setTimeout的时间间隔,也就是说即使我们把setTimeout的毫秒数设置为0,被调用的程序也没有马上启动。

setTimeout的最小时间间隔和浏览器及操作系统有关。在John Resig的《Javascript忍者的秘密》一书中提到--Browsers all have a 10ms minimum delay on OSX and a(approximately) 15ms delay on Windows.(在苹果机上的最小时间间隔是10毫秒,在Windows系统上的最小时间间隔大约是15毫秒),另外,MDC中关于setTimeout的介绍中也提到,Firefox中定义的最小时间间隔(DOM_MIN_TIMEOUT_VALUE)是10毫秒,HTML5定义的最小时间间隔是4毫秒。


猜你喜欢

转载自blog.csdn.net/Tomhs3000/article/details/80061501