今天在网上看到讨论浏览器的工作原理,我发现学习前端这么久了,竟然没有系统的学习过浏览器,知道的都是些零零散散的东西,于是趁现在空余时间,赶紧瞅瞅。
什么是线程?什么是进程? 进程包含多个线程,进程是操作系统最小的执行单位。 浏览器是一个多进程(multi-process),一个浏览器只有一个主进程(Browser Process)负责管理Tabs(窗口),协调Renderer Process 和其他Process 渲染进程(Renderer Process)是一个多线程的 它的主线程负责渲染页面和执行js以及事件循环 渲染进程的主线程是一个单线程(同一时间js执行线程和ui渲染线程只有一个在主线程上)
正是因为js是单线程的,很多的任务只能一个一个排队执行这对用户体验不好,所以就将任务分成了同步任务和异步任务。
简单的理解:
同步:获取元素、console.log()、alert、定义 变量…
异步: 事件、定时器、延时器 …
判断任务是同步还是异步同步任务直接在主线程执行、异步任务进入事件表并等待一个条件(时间,或者用户操作:例如 点击)。注册回调函数 异步任务进入事件队列当主线程空闲时(同步执行完成),事件队列中的任务才被推入主线程执行。其运行结果如下
实际上运行的结果并不符合咱们同步异步分类
我们对任务有了更加精细的分类
macro-task(宏任务):包括整体代码script,setTimeout,setIntervalmicro-task(微任务):Promise,process.nextTick进入整体代码(宏任务)后开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务.并且也要按照同步异步一起嵌套着来。 对照以上代码,其执行顺序为
//A.先执行同步代码 //1.执行宏任务(整段script代码) console.log('1') //2.执行微任务(promise) console.log('7'); //3.执行微任务process.nextTick //Node执行完所有同步任务才执行process.nextTick的任务队列 console.log('6'); //4. 执行异步代码 promise的then方法 console.log('8') //B.执行异步代码 //1.执行第一个定时器中的宏任务 console.log('第一个setTimeout') //2.执行第一个定时器中的微任务 console.log('第一个setTimeout内的promise') //3.执行第二个定时器中的宏任务 console.log('第二个setTimeout') //4.执行第二个定时器中的微任务 console.log('第二个setTimeout内的promise') //5.当所有的同步任务执行后执行process.nextTick //第一个定时器中的process.nextTick console.log('3'); //第二个定时器中的process.nextTick console.log('10'); //6.执行异步then函数 //先执行第一个定时器中的 console.log('第一个setTimeout内的promise的then') //先执行第二个定时器中的 console.log('第二个setTimeout内的promise的then')1.先执行同步宏任务,再执行同步微任务,其次是异步微任务 2.执行异步宏任务,再执行同步微任务,其次是异步微任务