You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
$.on("button","click",functiononClick(){setTimeout(functiontimer(){console.log("You clicked the button!");},2000);});console.log("Hi!");setTimeout(functiontimeout(){console.log("Click the button!");},5000);console.log("Welcome to loupe.");
Save + run 发生了什么:
执行的区域我们分为 Call Stack (调用栈)、Web Apis (浏览器环境的 API 线程)、Callback Queue(回调队列)
一、单线程的 Javascript
诞生之初,JavaScript 被设计为单线程、非阻塞、异步、解释性的语言,作为客户端脚本在网页浏览器环境运行,主要用来向 HTML 页面添加交互行为。
为了并发地处理事件,JavaScript 程序输入/输出是使用事件和回调函数执行的。例如,这意味着 JavaScript 可以在等待数据库查询返回信息时处理鼠标单击。ECMAScript ES6 引入了 Promise 用于优雅地处理异步事件,其可以使得传统的基于回调的异步代码更加清晰与简单。
在最新的 HTML5 中提出了 Web-Worker,但 javascript 是单线程这一核心仍未改变。所以一切 javascript 版的"多线程"都是用单线程模拟出来的,将来也不会变。
二、任务队列
单线程模式就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
为了解决排队等待的耗时问题,聪明的 Javascript 设计者将任务分为了:
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
任务分类:
主线程处理任务队列的运行机制如下:
三、什么是 Event Loop
主线程在空闲的时候从
task queue
中取出事件来执行,这个过程是循环不断的,所以整个的这种运行机制又称为 Event Loop(事件循环)。下图(转引自 Philip Roberts 的演讲《What the heck is the event loop anyway?》
Call Stack 例子
执行时发生了什么:
Event loop 例子
Save + run 发生了什么:
执行的区域我们分为 Call Stack (调用栈)、Web Apis (浏览器环境的 API 线程)、Callback Queue(回调队列)
$.on('button', 'click', ...)
;setTimeout(timeout, 5000)
setTimeout(√) 清空
setTimeout(timeout, 5000)
的回调函数 timeout;四、宏任务与微任务
当主线程空闲时(执行栈为空),主线程会先查看微任务队列,执行清空后再查看宏任务队列,并执行清空,如此反复循环。
micro-task(微任务):Promise.then、MutationObserver、process.nextTick(Node 环境)、setImmediate (Node 环境)
macro-task(宏任务):script 代码块、setTimeout、setInterval、I/O、UI rendering
举个例子:
下面是代码的执行分析:
new Promise
立即执行 log:1setTimeout
,注册其回调函数后分发到 宏任务队列Promise.resolve().then()
的回调函数Promise.resolve().then().then()
的回调函数Promise.resolve().then()
=》 log:3Promise.resolve().then().then()
=》 log:4task queue
非空setTimeout callback
log:2task queue
清空async/await 函数
因为
async/await
本质上还是基于Promise
的一些封装,而Promise
是属于微任务的一种。所以在实际使用上效果类似:async 函数在 await 之前的代码都是同步执行的,可以理解为 await 之前的代码属于new Promise
时传入的代码,await 之后的所有代码都是在Promise.then
中的回调。下面是代码的执行分析:
setTimeout callback
task queue
非空setTimeout callback
log:4task queue
为空参考
The text was updated successfully, but these errors were encountered: