之前看的文,感觉不太完整,于是找了篇详细的文章原文链接。翻译不正确的请指出,重在分享,如果有所收获就更好了。

Javascript是如何异步和单线程的?简短的回答是javascript语言是单线程的,异步行为不是它的一部分,相反,它是建立在浏览器(或编程环境)中的核心JavaScript语言之上,并通过浏览器API访问。

现在为了得到答案,让我写两个示例代码片段。

基本架构

  • :对象在堆中分配,表示大多数非结构化的内存区域。
  • :这表示JavaScript代码执行提供的单个线程,函数调用形成一个栈。
  • 浏览器或Web API是内置在你的web浏览器中,能够暴露浏览器和周围的计算机环境中的数据,并使用它执行游泳的复杂操作。它们不是JavaScript语言的一部分,而是基于核心JavaScript语言构建,为你的JavaScript代码中提供额外的超能力。例如,Geolocation API提供了一些简单的JavaScript构造,用于检索数据,所以你可以说,在Google map上绘制你的位置。在后台,浏览器实际上使用一些复杂的低级代码(例如C++)与设备的GPS硬件(或者任何可用于确定位置数据的信息)进行通信,检索位置数据,并将其返回到浏览器环境用来使用在你的代码中。但同样,这种复杂性是由API抽象出来的。

代码片段1:迷惑心灵

function main(){console.log('A');setTimeout(function display(){ console.log('B'); },0);console.log('C');
}
main();
//  Output
//  A
//  C
//  B
复制代码

这里,我们有一个主函数,它有两个console.log:将A和C输入到控制台上。它们中间是一个在0ms后将B输出到控制台上的setTimeOut调用。

  1. 调用主函数,首先将它推入到栈中。然后浏览器将主函数的第一个声明console.log('A')推入到栈中,执行此语句,并在完成后弹出,字母A显示在控制台上。
  2. 第二个声明setTimeout推入栈中并开始执行。setTimeout函数使用浏览器的API来延迟回调其中的函数。一旦交接给brower完成timer,这一帧就被推出。
  3. 当计时器在浏览器中运行来回调exec函数时,console.log(‘C’)被推入栈中。在这种特殊的情况下,由于提供的延迟是0ms,一旦浏览器接收到它(理想情况下),回调将被添加到消息队列中。
  4. 执行完主函数的最后一个语句,主函数从调用堆栈中弹出,从而堆栈为空。对于浏览器将任何消息从队列推送到调用堆栈中,调用堆栈必须为空。这就是为什么即使setTimeout中提供的延迟是0ms,exec的也必须等到调用堆栈中的所有帧的执行完成。
  5. 现在exec的回调被推入调用栈,接着执行。字母C显示在控制台上。这就是JavaScript的事件循环。

因此setTimeout(function,delayTime)中的delay参数不代表执行函数之后的精确时间延迟。它代表最小等待时间,之后在某个时间点执行该功能。

代码片段2:深入理解

function main(){console.log('A');setTimeout(function exec(){ console.log('B'); }, 0);runWhileLoopForNSeconds(3);console.log('C');
}
main();
function runWhileLoopForNSeconds(sec){let start = Date.now(), now = start;while (now - start < (sec*1000)) {now = Date.now();}
}
// Output
// A
// C
// B
复制代码
  • 函数runWhileLoopForNSeconds完全符合其名称所代表的含义,它会不断检查从调用时间开始经过的时间是否等于函数参数提供的秒数。要记住的要点是while循环(与许多其他循环一样)是一个阻塞语句,意味着它的执行发生在调用堆栈上,并且不使用浏览器API。因此它会阻止所有后续语句,直到它执行完成。
  • 所以在上面的代码中,即使setTimeout的延迟为0ms,但在while循环运行3s中,exec()回调会卡在消息队列中。只有在while循环在调用堆栈(单线程)上运行3s完成,调用堆栈变空之后,回调exec()被推入到调用堆栈并执行。
  • 因此setTimeout()中的delay参数不保证在计时器完成延迟后开始执行。它是延迟部分的最短时间。

[译]理解js中的event loop相关推荐

  1. 理解node.js中的 Event Loop

    node中的 "event loop" 正是node能处理高并发的核心所在.也正是因为它,node虽然在本质上是个单线程,却能让大量的操作处于后台运行.这篇文章将详细说明 even ...

  2. 正确理解javascript中的Event loop机制

    这两个星期一直在想着写一篇关于javascript中event Loop的文章.自从写完上一篇<Javascript捕捉(capturing)与冒泡(bubbling)的区别>之后,我抛出 ...

  3. node.js中对Event Loop事件循环的理解

    javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进 ...

  4. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  5. js 中的 Event Loop 以及 宏任务 与 微任务

    目录 前言 1.JS 的 执行引擎 与 执行环境 2.js 是单线程的 一.事件循环(Event Loop) 二.任务队列 三.宏任务 与 微任务 1.宏任务 2.微任务 3.宏任务与微任务的运行机制 ...

  6. 面试率 90% 的JS事件循环Event Loop,看这篇就够了!! !

    面试率 90% 的JS事件循环Event Loop,看这篇就够了!! ! 事件循环(Event Loop)大家应该并不陌生,它是前端极其重要的基础知识.在平时的讨论或者面试中也是一个非常高频的话题. ...

  7. JS 中的 event?event:window.event什么意思?求详解。

    JS 中的 event?event:window.event什么意思?求详解. 2013-04-16 00:01flying607 | 分类:JavaScript |浏览813次 <script ...

  8. 理解js中的面向对象

    目录 前言: 一点疑问: 1.封装 2.继承 原型链的查找机制 不容易理解的点: ----重点在最后---- 前言: js是一门面向对象的语言,但是又没有类的概念,虽然后来加入了class,但也就是个 ...

  9. 彻底理解js中this

    相关博文:http://blog.csdn.net/libin_1/article/details/49996815 彻底理解js中this的指向,不必硬背. 首先必须要说的是,this的指向在函数定 ...

最新文章

  1. python程序设计报告-20192416 实验四《Python程序设计》综合实践报告
  2. log_archive_dest_1设置报错
  3. kvm linux重置密码,kvm虚拟机操作相关命令及虚拟机和镜像密码修改
  4. 创新、颠覆、引领,从 0 到百亿美元市值的创操作指南
  5. 贪心问题JAVA_java背包问题(贪心法)
  6. flutter listview 滚动到底部_??一个高颜值Flutter版WanAndroid客户端
  7. 端口渗透·网站渗透过程 --21 ,22,873,3306,6379,8080(8080端口是针对CMS的渗透)...
  8. Android RatingBar使用Kotlin
  9. Go语言极速入门手册
  10. HDU 3790 最短路径问题 (最短路)
  11. Spark独到见解--Action算子总结
  12. 微信小程序全方位深度解析课程Dome-First项目module
  13. 计算机教学模式有待创新,计算机软件教学中教学评价模式的创新与探索
  14. excel sumifs多条件求和
  15. IDEA使用教程(一) 基础配置
  16. oracle中scott用户的创建
  17. Unity实战之牧师与魔鬼(动作分离版)
  18. 极验验证简介(待续)
  19. fprintf与fscanf
  20. 关于 ONLYOFFICE 的安卓 Android 手机版

热门文章

  1. linux_2.6内核内存缓冲与I/O调度机制:
  2. linux中的和||(linux中=和==效果是一样的)
  3. 最小树形图(朱刘算法)
  4. 尝鲜党:Nexus5、6刷安卓M教程
  5. 你必须会的DFS的递归实现与堆栈实现
  6. 插入排序之——直接插入排序(c/c++)
  7. 前端每日实战:164# 视频演示如何用原生 JS 创作一个数独训练小游戏(内含 4 个视频)...
  8. snpeff注释变异(variants)
  9. 读书笔记----javascript函数编程
  10. nginx的upstream问题记录