同步、异步、回调执行顺序之经典闭包setTimeout分析
聊聊同步、异步和回调
同步,异步,回调,我们傻傻分不清楚,
有一天,你找到公司刚来的程序员小T,跟他说:“我们要加个需求,你放下手里的事情优先支持,我会一直等你做完再离开”。小T微笑着答应了,眼角却滑过一丝不易觉察的杀意。
世界上的所有事情大致可以分为同步去做和异步去做两种。你打电话去订酒店,电话另一边的工作人员需要查下他们的管理系统才能告诉你有没有房间。
这时候你有两种选择:一种是不挂电话一直等待,直到工作人员查到为止(可能几分钟也可能几个小时,取决于他们的办事效率),这就是同步的。
另一种是工作人员问了你的联系方式就挂断了电话,等他们查到之后再通知你,这就是异步的,这时候你就可以干点其他事情,比如把机票也定了之类的
计算机世界也是如此,我们写的代码需要交给cpu去处理,这时候就有同步和异步两种选择
js是单线程的,如果所有的操作(ajax,获取文件等I/O操作<node>)都是同步的,遇到哪些耗时的操作,后面的程序必然被阻塞而不能执行,页面也就失去了响应,
因此js采用了事件驱动机制,在单线程模型下,使用异步回调函数的方式来实现非阻塞的IO操作,
那么什么是异步任务呢?(参考阮一峰老师《JavaScript运行机制》)
异步任务也就是 指主线程(stack栈)运行的过程中,当stack空闲的时候,主线程对event queque(队列)轮询(事实上一直在轮询)后,将异步任务放到stack里面进行执行;

(上图转引自Philip Roberts的演讲《Help, I'm stuck in an event-loop》))
简单的说,如果我们指定过回调函数,那么当事件发生时就会进入事件队列,等待主线程的(stack)空闲的时候,就会对event queue里面的回调读取并放到stack里面执行
我们经常说的可能是异步回调(当然也有同步回调),所以也就并不难理解,回调和异步之间其实并没有直接的联系,回调只是异步的一种实现方式,
通过这样的event loop我们其实可以分析出三者的执行顺序,即 同步 > 异步 > 回调
经典闭包setTimeout分析
今天同学问了我一个问题,我一看是一道经典的面试题,问题如下:

简单的这个问题改一下:
for (var i = 0; i <= 5; i++) {
setTimeout(function() {
console.log( i );
}, i*1000);
console.log( ' i : ' , i );
}
console.log( i );
相信我们很多人都遇到过这个问题,心中或许都有答案:

那么为什么并不是入门者心中所想要的结果嘞(为什么setTimeout中打印出i全部是6,而且是最后才打印出来呢)?
那么就让我们来梳理一下,第一部分event loop图片很直观的体现:"任务队列"可以放置异步任务的事件,也可以放置定时事件(setTimeout和setinterval),即指定某些代码在多少时间之后执行;
1、首先我们先来看一下他的主体结构: for循环的第一层是setTimeout函数,setTimeout函数中使用了一个匿名(回调)函数
2、还记的我们之前总结的执行顺序:同步 > 异步 > 回调 吧!
1)for循环和外层的 console.log()是同步的,setTimeout是回调执行,
所以按照执行顺序,先执行for循环,然后进入for循环中,他发现了一个setTimeout()回调(进入event queque事件队列,等待stack栈为空后读取并放入栈中后执行),这时候他并不会等待
而是继续执行 --> for循环内部的 console.log( ' i : ' , i ) --> for循环外部的console.log( i ) ,然后"任务队列"中的回调函数才进入到空Stack中开始执行;
我们在来用这个例子尝试一下上面的event loop图,更加直观的感受一下:

那么接下来可能会问怎么解决这个问题呢?我想最简单的当然是let语法了,
for (let i = 0; i <= 5; i++) {
setTimeout(function() {
console.log( i );
}, i*1000);
console.log( ' 1 : ' , i );
}
console.log( i );
我们都知道es5中变量作用域是函数,而es6却可以使用let声明一个具有块级作用域的i,在这里也就是for循环体;
在这里let本质上就是形成了一个闭包,那么写成es5的形式其实等价于:
var loop = function (_i) {
setTimeout(function() {
console.log( _i);
}, _i*1000);
console.log('2:',_i)
6 };
8 for (var _i = 0; _i <= 5; _i++) {
9 loop(_i);
}
总结
到这里,我们就完成了从同步、异步、回调的机制分析 到 setTimeout的经典案例的分析,JavaScript博大精深,我们需要了解他的机制去深入去挖掘他。
同步、异步、回调执行顺序之经典闭包setTimeout分析的更多相关文章
- 「JavaScript」同步、异步、回调执行顺序之经典闭包setTimeout分析
聊聊同步.异步和回调 同步,异步,回调,我们傻傻分不清楚, 有一天,你找到公司刚来的程序员小T,跟他说:“我们要加个需求,你放下手里的事情优先支持,我会一直等你做完再离开”.小T微笑着答应了,眼角却滑 ...
- js同步-异步-回调
出处:https://blog.csdn.net/u010297791/article/details/71158212(1)上面主要讲了同步和回调执行顺序的问题,接着我就举一个包含同步.异步.回调的 ...
- C# 同步 异步 回调 状态机 async await Demo
源码 https://gitee.com/s0611163/AsyncAwaitDemo 为什么会研究这个? 我们项目的客户端和服务端通信用的是WCF,我就想,能不能用异步的方式调用WCF服务呢?或者 ...
- 浅谈个人对客户端JavaScript同步、异步、执行顺序等概念的理解
一.同步和异步的概念. 同步:即按代码的顺序执行任务. 在下列代码中,按照同步概念,则是先打印1后打印2. console.log(1); console.log(2); 异步:即执行一个任务的同时执 ...
- 前端笔记之JavaScript(九)定时器&JSON&同步异步/回调函数&函数节流&call/apply
一.快捷位置和尺寸属性 DOM已经提供给我们计算后的样式,但是还是觉得不方便,因为计算后的样式属性值都是字符串类型. 不能直接参与运算. 所以DOM又提供了一些API:得到的就是number类型的数据 ...
- 【java回调】同步/异步回调机制的原理和使用方法
回调(callback)在我们做工程过程中经常会使用到,今天想整理一下回调的原理和使用方法. 回调的原理可以简单理解为:A发送消息给B,B处理完后告诉A处理结果.再简单点就是A调用B,B调用A. 那么 ...
- C#--委托的同步,异步,回调函数
原文地址 同步调用 委托的Invoke方法用来进行同步调用.同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行. using System; using System. ...
- python 管道 事件(Event) 信号量 进程池(map/同步/异步)回调函数
####################总结######################## 管道:是进程间通信的第二种方式,但是不推荐使用,因为管道会导致数据不安全的情况出现 事件:当我运行主进程的 ...
- C#基础知识之父子类,实例、静态成员变量,构造函数的执行顺序(经典示例)
父子类.示例.静态成员变量.构造函数的概念的基础理解完全可以利用下面的示例诠释,非常经典,直接上代码: public class ShowInfo { public ShowInfo(string i ...
随机推荐
- AForge.NET简介
AForge.NET是一个专门为开发者和研究者基于C#框架设计的,这个框架提供了不同的类库和关于类库的资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器 ...
- SQL Server中ORDER BY后面可以是表达式和子查询
假如SQL Server数据库中现在有Book表如下 CREATE TABLE [dbo].[Book]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [CreateTi ...
- Visual Studio 2012自动添加注释(如版权信息等)
转自:http://blog.163.com/guohuan88328@126/blog/static/69430778201381553150156/ 如何使用Visual Studio 2012给 ...
- Java 设计模式笔记
0. 说明 转载 & 参考大部分内容 JAVA设计模式总结之23种设计模式 1. 什么是设计模式 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设 ...
- js 排序,去重
前几天 有一个需求要做一个 勾选的按钮 ,用的前端框架时 extjs . 需求是这样的:选择数据后点击勾选 会把数据 放到一个全局变量里,然后点击另外一个提交按钮 弹出一个窗口 加载这些已经勾选的 ...
- Audit log report
- 软件架构方面基础-ESB \SOA \GEO-ESB
学习初稿 软件架构演变历史 SOA (Service-Oriented Architecture)面向服务的体系结构 它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起 ...
- 《面向对象程序设计》六 GUI
git传送门 我这无药可救的拖延症和懒癌orz 主界面 文件读取界面 提示界面 最初选择vs+mfc,发现许多自动生成的代码读不懂(不须懂),尝试qt后感觉人生迎来了希望,看了推荐的视频与教程稍微了解 ...
- Win10无法启动软件提示MSVCP110.dll丢失
遇到这种问题,第一种方法可以选择去https://www.microsoft.com/zh-CN/download/details.aspx?id=30679 官网去下载 vc++ 2012 安装和自 ...
- MySQL keepalived 双主.md
MySQL keepalived 双主搭建 环境说明 系统 IP 主机名 mysql keepalived VIP CentOS 6.8 192.168.197.61 C6-node1 5.6.36 ...