setTimeout与取号机之间的关系


说到setTimeout写过javascript的伙伴们一定不会陌生,去银行办过存取款业务的伙伴一定对取号机不会陌生。今天群里有个好伙伴在问setTimeout的问题,大伙你一言我一语,讲了很多,可是她听了之后还是不理解。我先不说她的问题,请先回忆一下,去银行或医院排队的时候,是不是要先去机器上取一个号码呀。也不知从几何时,取号机就开始流行起来了。不过这也确实是好事,不用一直站在那里排呀排,而且可以知道前面有多少人排在我前面,因此大可以放心的坐在椅子上刷微博,玩微信。等到叫你手中的号码时,就轮到你了。这个我相信大多数人都玩过,就不细说了。下面我要说的这个问题,或许可以用上面的情景来类比,以帮助理解。当然,比的不好,也可以吐槽。

for(var i=0;i<10;i++){
   var id = setTimeout(function(){
      console.log(id);
   },1000);

}

setTimeout与取号机之间的关系

那么问题来了,这个id是干嘛用的,为什么输出了10个4144 ? 

首先查了一下w3c,上面对setTimeout是这么解释的:setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。关于它的返回值解释在度娘上很少,或许是我搜的问题,最近google要FQ才能用了,不爽。我也不管他娘是怎么给它定义的,反正理解成系统分配给它的号码就行了,简单粗暴。这个号码与浏览器当前的运行环境有关。所以你运行上面的代码,不一定是这个数字. 这就好比同一个人去每个银行的取号机上拿到的号码不一定相同是一个道理。

学过计算机原理的人一般都会知道,cpu一次只能做一件事情,它把忙不过来的任务放在缓存区,比如优先级最高的排在一级缓存,次要的排在二级缓存,再次要的放内存,最后是硬盘。总之呢,是要排队一个一个的处理。cpu怕忙乱了,于是呢给每一个任务都排了一个号码,取一个专业点的名字,叫id,这样叫到谁,谁就开始执行。有时候,某些任务会被用户取消。比如岛国片看到一半,女朋友突然回来了,急忙关掉播放器。这时系统就会告诉cpu,播放岛国片的那个id用户取消了,cpu就跳过这个id不做了。 这就和取号机是一样样的,如果你取了号,又临时有事走了。广播叫的那个号码被你拿走了,你又不在。自然就不管你了。关于这个id七七八八就写了这么多,也不知道看官您整明白了没有。

下面接着说那个输出10个4144的问题。其实这个问题是一个老生常谈的问题了,本质上都是异步的问题。

我上面说了,setTimeout用于在指定的毫秒数后做某事,而for循环里边是当前立即开始要做的事。我们的cpu虽然一次只能做一件事,但是它的速度是很快的,一秒钟都可以完成N多件事情(N等于一个很大的数)。上面的代码等价于:

var id;
for(var i=0;i<10;i++){
    id = setTimeout(function(){
      console.log(id);
   },1000);
}

所以当第一个setTimeout执行的时候,for循环早就完成了,id的值也就是最后那个setTimeout返回的id。 所以输出10个一样的id值,也就不足为怪了。

如果想要查看每一个setTimeout返回的id是多少,直接这样写就可以了:

var id;
for(var i=0;i<10;i++){
    id = setTimeout(function(){
      //console.log(id);
   },1000);
   console.log(id)
}

虽然setTimeout里边的任务是指定时间后执行,但是它的id值是即时返回的,就比如你取号的时候,不管要过久才能轮到你,但是只要你点了取号机,它就会立即打印给你。

这个过程是同步的。当然,关于setTimeout还有很多知识点,也有很多坑,但是只要注意它这里有个异步的问题,大多数情况都可以避免。

本篇是原创,如果对你有帮助,请点击 推荐,如果有什么地方有疑问,欢迎跟贴探讨。


6 responses on “setTimeout与取号机之间的关系

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>