十四、JS同步异步知识点,重点(Node.js-fs模块补充篇)
(本片文章如果你能耐着性子看我,保证会对同步和异步有一个非常深刻的理解)
JavaScript是单线程执行,所谓的单线程呢就是指如果有多个任务就必须去排队,前面任务执行完成后,后面任务再执行。因为JavaScript是一门单线程语言,所以我们可以得出结论:
JavaScript是按照语句出现的顺序执行的
一、同步和异步

同步
如果在函数返回结果的时候,调用者能够拿到预期的结果(就是函数计算的结果),那么这个函数就是同步的.
console.log('hello');//执行后,获得了返回结果
如果函数是同步的,即使调用函数执行任务比较耗时,也会一致等待直到得到执行结果。(所以在JavaScript中对于耗时的操作或者时间不确定的操作,使用异步就成了必然的选择。)如下面的代码:
function wait(){
for(var i=0;i<9999999999;i++){
if (i==9999999999){
console.log('i需要慢慢的加1直到99999999999999');
return
}
}
}
wait();
console.log('要等到i增加到9999999999(也就是wait()函数执行完毕)才能打印出这句话,大概要等10秒左右');
上面代码中,函数wait是一个耗时程序,持续10秒左右,在它执行的这漫长的10秒中,下面的console.log()函数只能等待,这就是同步。所以在JavaScript中对于耗时的操作或者时间不确定的操作,使用异步就成了必然的选择。
异步
如果在函数返回的时候,调用者还不能够得到预期结果,而是将来通过一定的手段得到(例如回调函数),这就是异步。例如处理AJAX请求的线程、处理DOM事件的线程、定时器线程、读写文件的线程等等。 如果函数是异步的,发出调用之后,马上返回,但是不会马上返回预期结果。调用者不必主动等待,当被调用者得到结果之后会通过回调函数主动通知调用者。
function wait(){//下面每句打印的话前面的数字是她们在控制台打印出来之后的先后顺序
console.log('1:wait()函数开始执行了');
var time1 = (new Date()).getTime();//获取当前的unix时间戳
setTimeout(function () {
var time2=new Date().getTime();
while((time2-time1 > 5000)){
console.log('4:5秒过去了');
return
}
},5000)//等5秒然后获取当前的unix时间戳
console.log('2:wait()函数执行结束了');
}
wait();
console.log('3:虽然js会先执行上面的wait函数,并且里面有个5秒的定时器,但是定时器函数是异步的,意思就是说wait()函数里面的定时器启动,并开始计时的时候并不影响继续执行定时器之后的代码');
上面的代码的打印结果:

例二:
//打印出什么 3 3 3
for(var i=0;i<3;i++){
setTimeout(function(){//凡是异步操作,一定是在所有同步操作执行完毕之后才能执行,也就是for循环执行完毕之后才能执行定时器里面的代码,此时i=3了
console.log(i);
},100)
}
二、单线程与多线程
了解完同步和异步之后,我们再来看看我们的问题:单线程又怎么会有异步呢?
JavaScript其实就是一门语言,说是单线程还是多线程得结合具体运行环境。众所周知,js的运行环境就是浏览器,具体由js引擎取解析和执行。下面我们来了解下浏览器。
浏览器
一个浏览器通常由以下几个常驻的线程:
- 渲染引擎线程,负责页面的渲染
- js引擎线程,负责js的解析和执行
- 定时触发器线程,处理setInterval和setTimeout
- 事件触发线程,处理DOM事件
- 异步http请求线程,处理http请求
要注意的是渲染引擎和js引擎线程是不能同时进行的。渲染线程在执行任务的时候,js引擎线程会被挂起。因为若是在渲染页面的时候,js处理了DOM,浏览器就不知道该听谁的了
JS引擎
通常讲到浏览器的时候,我们会说到两个引擎:渲染引擎和JS引擎。
1、渲染引擎:Chrome/Safari/Opera用的是Webkit引擎,IE用的是Trdent引擎,FireFox用的是Gecko引擎。不同的引擎对同一个样式的实现不一致,就导致浏览器的兼容性问题。
2、JS引擎:js引擎可以说是js虚拟机,负责解析js代码的解析和执行。通常有以下步骤:
- 词法解析:将源代码分解位有意义的分词
- 语法分析:用语法分析器将分词解析成语法树
- 代码生成:生成机器能运行的代码
- 代码执行
不同浏览器的js引擎也各不相同,Chrome用的是V8,FireFox用的是SpiderMonkey,Safari用的是JavaScriptCore,IE用的是Chakra。
之所以说js是单线程就是因为浏览器运行时只开启一个js解释器,原因是若有两个线程操作DOM,浏览器就又晕了。
JavaScript是单线程的,但是浏览器不是单线程的。一些I/O操作,定时器的计时和事件监听是由其他线程完成的。
三、消息队列与事件循环
由上面浏览器一篇的介绍可以知道,浏览器中多个线程的合作完成了异步的操作,那么异步的回调函数又是怎样完成执行的呢?
这就需要了解消息队列和事件循环了。
如上图所示,左边的栈存储的是同步任务,就是那些能立即执行、不耗时的任务,如变量和函数的初始化、事件的绑定等等那些不需要回调函数的操作都可归为这一类。
右边的堆用来存储声明的变量、对象。下面的队列就是消息队列,一旦某个异步任务有了响应就会被推入队列中。如用户的点击事件、浏览器收到服务的响应和setTimeout中待执行的事件,每个异步任务都和回调函数相关联。
JS引擎线程用来执行栈中的同步任务,当所有同步任务执行完毕后,栈被清空,然后读取消息队列中的一个待处理任务,并把相关回调函数压入栈中,单线程开始执行新的同步任务。
JS引擎线程从消息队列中读取任务是不断循环的,每次栈被清空后,都会在消息队列中读取新的任务,如果没有新的任务,就会等待,直到有新的任务,这就叫事件循环。
上图以AJAX异步请求为例,发起异步任务后,由AJAX线程执行耗时的异步操作,而JS引擎线程继续执行堆中的其他同步任务,直到堆中的所有异步任务执行完毕。然后,从消息队列中依次按照顺序取出消息作为一个同步任务在JS引擎线程中执行,那么AJAX的回调函数就会在某一时刻被调用执行。
十四、JS同步异步知识点,重点(Node.js-fs模块补充篇)的更多相关文章
- Edge.js:让.NET和Node.js代码比翼齐飞
通过Edge.js项目,你可以在一个进程中同时运行Node.js和.NET代码.在本文中,我将会论述这个项目背后的动机,并描述Edge.js提供的基本机制.随后将探讨一些Edge.js应用场景,它在这 ...
- [Node.js] 01 - How to learn node.js
基本概念 链接:https://www.zhihu.com/question/47244505/answer/105026648 链接:How to decide when to use Node.j ...
- node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法
1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...
- node.js前后台交互示例 -- 使用node.js实现用户注册功能
node.js环境自行搭建,参考菜鸟教程的node.js就可以. 1 通过ajax提交index.html中form表单 register.html文件如下: <!doctype html> ...
- node.js day01学习笔记:认识node.js
Node.js(JavaScript,everywhere) 1.Node.js 介绍 1.1. 为什么要学习Node.js 企业需求 + 具有服务端开发经验更好 + front-end + back ...
- io.js - 兼容 NPM 平台的 Node.js 新分支
io.js(JavaScript I/O)是兼容 NPM 平台的 Node.js 新分支,由 Node.js 的核心开发者在 Node.js 的基础上,引入更多的 ES6 特性,它的目的是提供更快的和 ...
- 【node】fs模块,文件和目录的操作
检查文件是否存在,查询文件信息 fs.stat() fs.stat('./server.js', function (err, stat) { if (stat && stat.isF ...
- node的fs模块使用————node
node的fs模块使用----node fs模块是调用文件的模块. var fs=require('fs'); //引用模块. //查看文件信息 fs.stat('index.txt',functio ...
- js 同步 异步 宏任务 微任务 文章分享
分享一篇 写的很好的 宏任务 微任务 同步异步的文章 文章原地址: https://juejin.im/post/59e85eebf265da430d571f89 这一次,彻底弄懂 JavaScri ...
随机推荐
- 分享一道阿里巴巴(蚂蚁金服)Java笔试题
编写一个函数验证一个给定的9x9 整数矩阵是否符合数独的特性:a) 每个单元格数字为 1-9b) 每行的9个数不重复c) 每列的9个数不重复d) 如图中分割的9个小3x3矩阵,每个小矩阵里9个数不重复 ...
- 1100 Mars Numbers
题意:进制转换. 思路:注意当数字是13的倍数时,只需高位叫法的单词.比如26,是“hel”,而不是“hel tret”.我被坑在这里了!对应语句1的处理.另外,在输入n和n个字符串之间需要一个吸收字 ...
- 众包高效实用的.NET开源项目
1.Akka.NET: 概述:更轻松地构建强大的并发和分布式应用. 简介:Akka.NET是一个用于在.NET和Mono上构建高度并发,分布式和容错的事件驱动应用程序的工具包和运行时. 开源地址:ht ...
- C/S模式客户端连接服务器连接不上的问题
C/S模式客户端连接服务器连接不上的问题 1.服务器电脑防火墙关闭 2.服务器端SQL SERVER2008R: 配置工具--SQL SERVER配置管理器 MSSQLSERVER协议.客户端协议(S ...
- delphi c++builder 判断工程类型 超级系统变量
d:\program files (x86)\embarcadero\studio\16.0\SOURCE\RTL\SYS\SysInit.pas ModuleIsLib: Boolean; ...
- openark对MySQL进行Online_DDL
1.用oak对表sbtest1做添加字段和增加索引的Online DDL openark kit 提供一组小程序,用来帮助日常的 MySQL 维护任务,可代替繁杂的手工操作. 包括: oak-appl ...
- hadoop 小知识点
------------------------------------------- 配置hadoop的最小blocksize,必须是512的倍数. [hdfs-site.xml] dfs.name ...
- 机器学习工具Octave安装(Win10环境)
介绍 Octave是一个旨在提供与MATLAB语法兼容的开放源代码计算与数值分析的工具:同时也是GNU成员之一.Octave最初的设计以MATLAB为模板,在功能上与MATLAB有许多相似之处.但相较 ...
- Lambda02 函数式接口
1 java8默认提供的函数式接口 1.1 Predicate /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rig ...
- AntD02 Table组件的使用
1 前提准备 1.1 创建一个angular项目 1.2 将 Ant Design 整合到 Angular 项目中 1.3 官方文档 点击前往 2 简单使用 <nz-table #rowSele ...

