zoukankan      html  css  js  c++  java
  • 《无所不能的JavaScript编程系列:setTimeout 简笔》

    前言:问题引出

      JavaScript中会经常用到setTimeout来推迟一个函数的执行,如:

    1 setTimeout(function(){alert("Hello World");},1000)

      它的意思是会在执行到这句话后延迟1秒钟(1000毫秒)来弹出alert窗口。

      那么再看这一段:

    1 function a() {
    2     setTimeout(function() {alert(1)}, 0);
    3     alert(2);
    4 }

      注意,这段代码中的setTimeout延迟设为了0,就是延迟0毫秒,貌似是不做任何延迟立刻执行。但实际的执行结果确是先弹出2再弹出1,这是为什么呢?JavaScript API文档明确定义第二个参数意义为隔多少毫秒后,回调方法就会被执行。这里设成0毫秒,理所当然就立即被执行了!?这得从Javascript调用堆栈(call stack)和setTimeout的功能说起。

    问题剖析

      首先,JavaScript引擎是单线程运行的,浏览器无论在什么时候都有且只有一个线程在运行JavaScript程序,即同一时间只执行一条代码,所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。

      其次,和其他的编程语言一样,Javascript中的函数调用也是通过堆栈实现的。如上例中,在执行函数a的时候,函数a先入栈,如果不给alert(1)加setTimeout,那么alert(1)第2个入栈,最后是alert(2)。但现在给alert(1)加上setTimeout后,alert(1)就被加入到了一个新的堆栈中等待,并“尽可能快”的执行。这个尽可能快就是指在a的堆栈完成后就立刻执行,因此实际的执行结果就是先alert(2),再alert(1)。在这里setTimeout实际上是让alert(1)脱离了当前函数调用堆栈。

    扩展:AJAX是否真的异步?

      既然说JavaScript是单线程运行的,那么XMLHttpRequest在连接后是否真的异步?

      其实请求确实是异步的,不过这请求是由浏览器新开一个线程请求,当请求的状态变更时,如果先前已设置回调,这异步线程就产生状态变更事件放到 JavaScript引擎的处理队列中等待处理,当任务被处理时,JavaScript引擎始终是单线程运行回调函数,具体点即还是单线程运行onreadystatechange所设置的函数。

    扩展:setTimeout的 应用场景

    一、解决双击事件触发单击事件的冲突

      提示:默认双击会先触发单击事件,使用延迟单击事件进行处理。

     1 function click(){
     2   isdb=false;
     3   window.setTimeout(cc, 500)
     4   function cc(){
     5     if(isdb!=false)return;
     6     alert("单击")
     7   }
     8 }
     9 function dblclick(){
    10   isdb=true;
    11   alert("双击")
    12 }

    二、解决双击事件触发单击事件的冲突

      AJAX请求后台,调用webservice或调用大量数据查询等情况造成前台一直处于loading加载框的情况,可以使用setTimeout来解决。

      部分JQ源码如下:

    1 if ( s.async && s.timeout > 0 ) {
    2     timeoutTimer = setTimeout(function() {
    3         jqXHR.abort("timeout");
    4     }, s.timeout );
    5 }

    编后语

      本博文简单介绍了setTimeout和JS单线程的知识,这块水其实很深,但这边只做一个随笔。有兴趣的同学,推荐阅读jQuery作者John的一篇文章:How JavaScript Timers Work,你会对JavaScript单线程本质和setTimeout以及setInterval有更加深刻的理解。

      http://ejohn.org/blog/how-javascript-timers-work/ 

      当你理解了JS的单线程和堆栈原理,那在使用JS进行高级程序编写中,必然会得心应手。

      当你还在说JavaScript是一门玩具型的脚本语言时,它也在远处嘲笑你对它不够了解。

      

  • 相关阅读:
    最近一周的日期选择设置
    使用两个 Windows 窗体 DataGridView 控件创建一个主/从窗体
    WCF使用小例子
    SQL Server中JOIN的用法
    C#设计模式(13)——代理模式(Proxy Pattern)
    SQL四种语言:DDL,DML,DCL,TCL
    Log4Net组件的应用详解
    JSP九大内置对象详解
    Objective-C:自定义Block函数
    C语言:指针的几种形式二
  • 原文地址:https://www.cnblogs.com/shanrengo/p/6413435.html
Copyright © 2011-2022 走看看