为什么JavaScript是单线程?

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。

JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

Event Loop

参考地址:Event Loop 这个循环你晓得么?(附 GIF 详解)-饿了么前端

任务队列的本质

  • 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  • 主线程之外,还存在一个”任务队列”(task queue)。只要异步任务有了运行结果,就在”任务队列”之中放置一个事件。
  • 一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  • 主线程不断重复上面的第三步。

异步任务

  • setTimeOut、setInterval
  • DOM 事件
  • Promise

JavaScript 实现异步编程的方法?

  • 回调函数
  • 事件监听
  • 发布/订阅
  • Promises 对象
  • Async 函数[ES7]

关于 setTimeOut、setImmediate、process.nextTick()的比较

setTimeout()

将事件插入到了事件队列,必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。
当主线程时间执行过长,无法保证回调会在事件指定的时间执行。
浏览器端每次setTimeout会有4ms的延迟,当连续执行多个setTimeout,有可能会阻塞进程,造成性能问题。

setImmediate()

事件插入到事件队列尾部,主线程和事件队列的函数执行完成之后立即执行。和setTimeout(fn,0)的效果差不多。
服务端node提供的方法。浏览器端最新的api也有类似实现:window.setImmediate,但支持的浏览器很少。

process.nextTick()

插入到事件队列尾部,但在下次事件队列之前会执行。也就是说,它指定的任务总是发生在所有异步任务之前,当前主线程的末尾。
大致流程:当前”执行栈”的尾部–>下一次Event Loop(主线程读取”任务队列”)之前–>触发process指定的回调函数。
服务器端node提供的办法。用此方法可以用于处于异步延迟的问题。
可以理解为:此次不行,预约下次优先执行。

浏览器的Tasks、microtasks、 queues 和 schedules

Promise

Promise本身是同步的立即执行函数, 当在 executor 中执行 resolve 或者 reject 的时候, 此时是异步操作, 会先执行 then/catch 等,当主栈完成后,才会去调用 resolve/reject 中存放的方法执行,打印 p 的时候,是打印的返回结果,一个 Promise 实例。

async await

Async/Await就是一个自执行的generate函数。利用generate函数的特性把异步的代码写成“同步”的形式。

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出了 async 函数体。

JS基础-事件队列的更多相关文章

  1. Node.js基础与实战

    Node.js基础与实战 Node.jsJS高级进阶 NODE原理与解析 REPL交互环境 模块与NPM Buffer缓存区 fs文件操作 Stream流 TCP&UDP 异步编程 HTTP& ...

  2. js基础进阶--关于setTimeout的思考

    欢迎访问我的个人博客:http://www.xiaolongwu.cn 先热身 看看下面的额代码会打印出什么? for (var i = 0; i < 5; i++) { setTimeout( ...

  3. js 基础篇(点击事件轮播图的实现)

    轮播图在以后的应用中还是比较常见的,不需要多少行代码就能实现.但是在只掌握了js基础知识的情况下,怎么来用较少的而且逻辑又简单的方法来实现呢?下面来分析下几种不同的做法: 1.利用位移的方法来实现 首 ...

  4. js 基础

    js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划():避 ...

  5. js基础练习二之简易日历

    今天学到了js基础教程3,昨天的课后练习还没来的及做,这个是类似简易日历的小案例,视频还没听完,今晚继续...... 先看效果图: 其实做过前面的Tab选项卡,这个就很好理解了,通过鼠标放在不同月份月 ...

  6. [JS复习] JS 基础知识

    项目结尾,空闲时间,又把<JS 基础知识> 这本书过了一遍,温故知新后,很多知其然不知其所以然的内容 豁然开朗. [1. 用于范围的标签] display  :inline or bloc ...

  7. JS基础(超级简单)

    1     JS基础(超级简单) 1.1 数据类型 1.1.1   基本类型: 1)        Number:特别注意:NaN的检测方法:Nan!=NaN;或者使用isNaN方法 2)       ...

  8. js基础到精通全面教程--JS教程

    适合阅读范围:对JavaScript一无所知-离精通只差一步之遥的人 基础知识:HTML JavaScript就这么回事1:基础知识 1 创建脚本块 1: <script language=”J ...

  9. JS基础知识总结

      js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划() ...

随机推荐

  1. 【Java】面向对象初探

    前段时间经历了一段心态浮躁期,这让我想起了自己最初的计划,要提升自己知识体系的广度.前几年一直做的是web前端这一块的工作,但我希望通过自己在学习Java这样的过程来提升自己的知识广度. 面向对象概述 ...

  2. JS如何在不给新空间的情况下给数组去重?

    1.先排序,在让相邻元素对比去重 const nums = [3, 1, 1, 5, 2, 3, 4, 3, 5, 5, 6, 4, 6, 6, 6]; Array.prototype.arrayNo ...

  3. 力扣(LeetCode)第一个错误的版本 个人题解

    你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最新版本没有通过质量检测.由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的. 假设你有 n 个版本 [1, ...

  4. C语言|博客作业01

    2.1你对计算机科学与技术的了解是怎样? 一开始,我并不知道计科和软件的区别,甚至以为这是一种专业的两种叫法.进了大学之后,才一下子懂了,计科就是计科,它和软件虽有相同之处,但是终究是不一样的.计科涉 ...

  5. 目录(cd mkdir rmdir rm pwd ls) 文件(ln touch mv rm cat more head rail) 文件权限(chmod chown chgrp) 文件通配符(* ? [])

    记住Linux目录树的结构是一个称职Linux系统管理员的必备素质! 目录漫游cd   cd - 目录显示pwd 目录管理 mkdir -p a/b/c/1 parent创建多层目录 -m 700   ...

  6. 关于 “'sqlite3' 不是内部或外部命令.....”问题

    学习django 按书上的  执行 manage.py dbshell 时, 报“'sqlite3' 不是内部或外部命令,也不是可运行的程序 或批处理文件.” 也就是指,环境变量中没有“sqlite3 ...

  7. 你的文章里为什么不放源码Github链接了

    "你的文章里为什么不放源码Github链接了?",一个读者这么问我 我把这张图发给了他,这是我之前放文章中Demo源码的Github仓库 他一脸疑惑,问我怎么了 经常使用Githu ...

  8. 突破至暗时刻,HCIE-RS的6个月成就之路

    我是今年四月份报的HCIE培训,到考完面试总共六个月的时间,对于HCIE整个考试的流程来说,六个月的时间不短,但也不是很长.尤其是面试,需要花费大量的时间和精力,下面我就把我整个备考历程做个简单的分享 ...

  9. Redis系列(三):Redis集群的水平扩展与伸缩

    一.Redis集群的水平扩展 Redis3.0版本以后,有了集群的功能,提供了比之前版本的哨兵模式更高的性能与可用性,但是集群的水平扩展却比较麻烦,接下来介绍下Redis高可用集群如何做水平扩展,在原 ...

  10. enable_shared_from_this用法分析

    一.背景 在为什么需要异步编程文章末尾提到,"为了使socket和缓冲区(read或write)在整个异步操作的生命周期一直保持活动,我们需要采取特殊的保护措施.你的连接类需要继承自enab ...