聊聊同步、异步和回调

同步,异步,回调,我们傻傻分不清楚,

有一天,你找到公司刚来的程序员小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分析的更多相关文章

  1. 「JavaScript」同步、异步、回调执行顺序之经典闭包setTimeout分析

    聊聊同步.异步和回调 同步,异步,回调,我们傻傻分不清楚, 有一天,你找到公司刚来的程序员小T,跟他说:“我们要加个需求,你放下手里的事情优先支持,我会一直等你做完再离开”.小T微笑着答应了,眼角却滑 ...

  2. js同步-异步-回调

    出处:https://blog.csdn.net/u010297791/article/details/71158212(1)上面主要讲了同步和回调执行顺序的问题,接着我就举一个包含同步.异步.回调的 ...

  3. C# 同步 异步 回调 状态机 async await Demo

    源码 https://gitee.com/s0611163/AsyncAwaitDemo 为什么会研究这个? 我们项目的客户端和服务端通信用的是WCF,我就想,能不能用异步的方式调用WCF服务呢?或者 ...

  4. 浅谈个人对客户端JavaScript同步、异步、执行顺序等概念的理解

    一.同步和异步的概念. 同步:即按代码的顺序执行任务. 在下列代码中,按照同步概念,则是先打印1后打印2. console.log(1); console.log(2); 异步:即执行一个任务的同时执 ...

  5. 前端笔记之JavaScript(九)定时器&JSON&同步异步/回调函数&函数节流&call/apply

    一.快捷位置和尺寸属性 DOM已经提供给我们计算后的样式,但是还是觉得不方便,因为计算后的样式属性值都是字符串类型. 不能直接参与运算. 所以DOM又提供了一些API:得到的就是number类型的数据 ...

  6. 【java回调】同步/异步回调机制的原理和使用方法

    回调(callback)在我们做工程过程中经常会使用到,今天想整理一下回调的原理和使用方法. 回调的原理可以简单理解为:A发送消息给B,B处理完后告诉A处理结果.再简单点就是A调用B,B调用A. 那么 ...

  7. C#--委托的同步,异步,回调函数

    原文地址 同步调用 委托的Invoke方法用来进行同步调用.同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行. using System; using System. ...

  8. python 管道 事件(Event) 信号量 进程池(map/同步/异步)回调函数

    ####################总结######################## 管道:是进程间通信的第二种方式,但是不推荐使用,因为管道会导致数据不安全的情况出现 事件:当我运行主进程的 ...

  9. C#基础知识之父子类,实例、静态成员变量,构造函数的执行顺序(经典示例)

    父子类.示例.静态成员变量.构造函数的概念的基础理解完全可以利用下面的示例诠释,非常经典,直接上代码: public class ShowInfo { public ShowInfo(string i ...

随机推荐

  1. IAM页面是在统一区分配的还是在混合区分配的?

    IAM页面是在统一区分配的还是在混合区分配的? IAM页面的作用这里就不说了,网上的资料很多 文章中用到的工具:查看SQLSERVER内部数据页面的小插件Internals Viewer 先建立四张表 ...

  2. OverAPI.com – 史上最全的开发人员在线速查手册

    不管你是多么优秀的程序员,你都不可能记住一切.在你编写程序的过程中碰到问题需要查阅手册的时候,若有现成的在线手册可参考则可以为你节省很多时间.为了方便各位朋友,我向大家推荐一个非常棒的在线手册索引网站 ...

  3. crm lookup

    1. 大家都知道CRM 里面的Lookup 保存了相关实体的GUID,让我们深入的了解一下CRM Lookup.当我们在2个实体间建立关系的时候,CRM自动生成了一些attributes来保存相关实体 ...

  4. Zabbix添加Ping外网IP监控

    1.先添加一个HOST,只填写IP即可,如10.1.1.1 2.选择一台客户端,新建item,如下: 3.新建trigger: 注:icmpping[<target>,<packet ...

  5. 中式台球 规则 ( ChinaBilliards )

    中式台球比赛规则 中式台球兴起于上世纪八十年代末,之前叫法有“中式8球”.“中式9球”.“十六彩”.“美式落袋”.“普尔“.”八球””等等.中国台球协会于2012年宣布统一该项运动称呼,定名为“中式台 ...

  6. python基础学习6----字符串操作

    一.重复输出字符串 print('hello'*20)#输出20个hello 二.通过索引获取字符串中字符 print('helloworld'[2:])#输出lloworld 三.关键字 in pr ...

  7. 使用C#获取Windows Phone手机的各种数据(转)

    转自:http://www.sum16.com/desinger/use-c-sharp-get-windows-phone-information.html 使用C#获取Windows Phone手 ...

  8. October 29th, 2017 Week 44th Sunday

    There was another life that I might have had, but I am having this one. 我明明可以过另一种生活,但我却选择了这一种. Be re ...

  9. 【Alpha 冲刺】 9/12

    今日任务总结 人员 今日原定任务 完成情况 遇到问题 贡献值 胡武成 完善API文档,并初步使用SpringMVC产生编写部分API 已完成 孙浩楷 完成课程通知页面(及发布通知的弹窗) 已完成 胡冰 ...

  10. PyQt5--MenuBar

    # -*- coding:utf-8 -*- ''' Created on Sep 13, 2018 @author: SaShuangYiBing ''' import sys from PyQt5 ...