《无所不能的JavaScript编程系列:setTimeout 简笔》
前言:问题引出
JavaScript中会经常用到setTimeout来推迟一个函数的执行,如:
setTimeout(function(){alert("Hello World");},1000)
它的意思是会在执行到这句话后延迟1秒钟(1000毫秒)来弹出alert窗口。
那么再看这一段:
function a() {
setTimeout(function() {alert(1)}, 0);
alert(2);
}
注意,这段代码中的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的 应用场景
一、解决双击事件触发单击事件的冲突
提示:默认双击会先触发单击事件,使用延迟单击事件进行处理。
function click(){
isdb=false;
window.setTimeout(cc, 500)
function cc(){
if(isdb!=false)return;
alert("单击")
}
}
function dblclick(){
isdb=true;
alert("双击")
}
二、解决双击事件触发单击事件的冲突
AJAX请求后台,调用webservice或调用大量数据查询等情况造成前台一直处于loading加载框的情况,可以使用setTimeout来解决。
部分JQ源码如下:
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout(function() {
jqXHR.abort("timeout");
}, s.timeout );
}
编后语
本博文简单介绍了setTimeout和JS单线程的知识,这块水其实很深,但这边只做一个随笔。有兴趣的同学,推荐阅读jQuery作者John的一篇文章:How JavaScript Timers Work,你会对JavaScript单线程本质和setTimeout以及setInterval有更加深刻的理解。
http://ejohn.org/blog/how-javascript-timers-work/
当你理解了JS的单线程和堆栈原理,那在使用JS进行高级程序编写中,必然会得心应手。
当你还在说JavaScript是一门玩具型的脚本语言时,它也在远处嘲笑你对它不够了解。
《无所不能的JavaScript编程系列:setTimeout 简笔》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- Huawei 常用基本配置命令一
华为交换机的三种视图: 用户视图, 系统视图, 接口视图 用户视图: 刚开始登入交换机时的视图,一般看到的是尖括号<> . save // 配置完交换机后保存当前配置的命令 system- ...
- ActiveX多线程回调JavaScript
http://www.cnblogs.com/zdxster/archive/2011/01/27/1945872.html
- 使用ubuntu过程中遇到的问题汇总
使用ubuntu过程中遇到的问题汇总 1.使用图形界面设置免密码登录之后,改回密码登陆失效 解决方案: https://askubuntu.com/questions/211084/how-do-i- ...
- Alpha冲刺报告(9/12)(麻瓜制造者)
今日已完成 邓弘立: 正在进行主页逻辑的编写 符天愉: 部署商品发布和物品需求的接口 江郑: 尝试完善接口文档,进行进一步测试 刘双玉: 编写接口说明 肖小强: 进行逻辑模块的编写 李佳铭: 修改了U ...
- 细数垃圾邮箱客户端 Live Mail 的BUG
以前用XP系统,里面自带的有outlook,使用中还行,不过bug也不少,常见的如 1.查找,邮件多了后,常常查找不到: 2.有时收件箱什么的突然空白,或部分邮件不见了(2G大小限制,超过了就不能做移 ...
- node版本查看管理工具
1.nvm : 有点坑爹,安装完后,发现node not found ,最后卸载了,重装node 2.bower :(前端)包管理器(选用) //安装方法 npm install bower -g / ...
- [转]vue全面介绍--全家桶、项目实例
慢慢了解vue及其全家桶的过程 原文http://blog.csdn.net/zhenghao35791/article/details/67639415 简介 “简单却不失优雅,小巧而不乏大匠”. ...
- libco协程库上下文切换原理详解
缘起 libco 协程库在单个线程中实现了多个协程的创建和切换.按照我们通常的编程思路,单个线程中的程序执行流程通常是顺序的,调用函数同样也是 “调用——返回”,每次都是从函数的入口处开始执行.而li ...
- 「2017 山东一轮集训 Day5」字符串
题目 比较神仙的操作啊 首先先考虑一个串的做法,我们有两种:SA或SAM,其中SAM又有两种,拓扑图上的\(dp\)和\(parent\)上随便统计一下 显然这道题\(SA\)和\(parent\)树 ...
- apache出现You don’t have permission to access / on this server问题的解决
今天在部署一个系统时,在apache中新开了一个VirtualHost,然后设置了DocumentRoot,等访问时却提示“You don’t have permission to access / ...