基础:
浏览器 -- 多进程,每一个tab页独立一个浏览器渲染进程(浏览器内核)javascript
每一个浏览器渲染进程是多线程的,主要包括:
GUI渲染线程java
JS引擎线程ajax
注意,GUI渲染线程与JS引擎线程是互斥的,因此若是JS执行的时间过长,这样就会形成页面的渲染不连贯,致使页面渲染加载阻塞。编程
事件触发线程数组
注意,因为JS的单线程关系,因此这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)promise
定时器触发线程浏览器
注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。网络
异步HTTP请求线程多线程
正文:并发
程序中如今运行的部分和未来运行的部分之间的关系就是异步编程的核心
ajax请求的异步:发出请求时,未来才能得到请求返回结果
—— 应该避免同步ajax请求,浏览器UI会被锁定并阻塞全部用户交互
异步基于事件循环机制 —— JavaScript引擎只是一个按需执行代码片断的环境,而这个需求是由其运行环境决定的:当遇到须要等待某些条件(网络数据、定时器计时到期等),条件知足后,运行环境才会把回调函数插入到事件循环队列中(参考基础资料 事件触发线程、定时器线程)
书中提到:ES6精确指定了事件循环的工做细节,在技术上将其归入了javascript引擎的势力范围,不是只由宿主环境管理,怎么理解?? 和前文基础部分对于浏览器渲染进程包含的多个线程之间关系有必定出入么?
异步和并行意义彻底不一样!!
并行 —— 同步执行 ,对于多线程编程,内存的共享提高了复杂度
异步 —— 交替调度
Javascript是单线程执行,从不跨线程共享数据
var a = 1,b=2 function foo(){ a = a + 1; b = b*2 } function bar(){ a = a * 2; b = b + 1; } // ajax(...)是某个库中提供的函数 ajax( 'http://some.url.1', foo ); ajax( 'http://some.url.2', bar );
因为js的单线程执行特性,foo() bar()函数内部的代码具备原子性
虽然foo() bar()存在竞态致使 a,b的最终值并不肯定
但这种不肯定性是在函数执行顺序上的(两个ajax返回的顺序)
旨在说明 “并发” 的几种状况,在js中看似并发实际是由单线程事件循环机制实现的
均以两个ajax请求的回调函数内执行不一样代码为例:
ES6引入,任务队列(job queue) —— 挂在事件循环队列的每一个tick以后的一个队列, 在事件循环的每一个tick中,可能出现的异步动做不会添加一个完整的新事件到事件循环队列中,而是会在当前tick的任务队列末尾添加一个项目(一个任务)
理论上说,任务队列可能致使无限任务循环
回调函数是javascript异步的基本单元
这章主要讨论回调这种自javascript诞生以来就存在的异步方式存在什么问题(思惟上的(大脑搞不定)、写法上的(嵌套、硬编码)、信任问题(控制反转)等),以引出下一章对新的异步方式Promise的讨论
调用回调过早 调用回调过晚(或不被调用) 调用回调次数过少或过多 未能传递所需的环境和参数 吞掉可能出现的错误和异常
针对回调的问题能够用一些特定逻辑来解决:
好比回调传入两种:正确、错误 或 error-first模式
针对回调过早问题:强制回调封装
但这些解决方案并不通用、且须要每次重复编写、难以复用
setTimeout(...)只是保证了回调函数不会在指定时间间隔以前执行,时间间隔以后插入到事件循环队列中,但此时队列中可能有多个项目
我的理解:
事件循环 -> 基于事件循环队列,其维护者不是js引擎,当js引擎执行到须要等待某个条件完成的代码时(ajax,setTimeout等),会交给当前运行环境执行并提供一个回调函数(运行环境可能使用其余线程),js引擎继续执行接下来的代码;条件知足后,运行环境将回调函数插入到事件循环队列的末尾,js引擎会从事件循环队列中获取代码执行
任务队列 -> 首先明确任务队列的位置:挂在事件循环队列的每一个tick以后的一个队列,当出现一个新的任务时,老是挂到当前事件循环tick结尾处!搞清楚如下代码的执行顺序就能初步了解任务队列与事件循环队列的关系了:
console.log('A'); setTimeout( function(){ console.log('B'); },0) var p = new Promise((resolve, reject)=>{ console.log('C'); return Promise.resolve(console.log('D')); // 嵌套promise }) 输出顺序: A C D B
另外,任务队列是由js引擎本身控制的 @TODO 了解具体实现方式