JS 是单线程的,也就是同一个时刻只能做一件事情。
那么思考:为什么浏览器可以同时执行异步任务呢?因为浏览器是多线程的。
当 JS 需要执行异步任务时,浏览器会另外启动一个线程去执行该任务。
也就是说,“JS 是单线程的”指的是执行 JS 代码的线程只有一个,是浏览器提供的 JS 引擎线程(主线程)。浏览器中还有定时器线程和 HTTP 请求线程等,这些线程主要不是来跑 JS 代码的。
比如主线程中需要发一个 AJAX 请求,就把这个任务交给另一个浏览器线程(HTTP 请求线程)去真正发送请求,待请求回来了,再将 callback 里需要执行的 JS 回调交给 JS 引擎线程去执行。即浏览器才是真正执行发送请求这个任务的角色,而 JS 只是负责执行最后的回调处理。所以这里的异步不是 JS 自身实现的,其实是浏览器为其提供的能力。
JavaScript是一门单线程的语言,它的异步和多线程的实现是通过eventloop事件循环机制来实现的,大概由三个部分组成:
1. JS 在解析一段代码时,会将同步代码按顺序排在某个地方,即执行栈,然后依次执行里面的函数。
2. 当遇到异步任务时就交给其他线程处理。
3. 待当前执行栈所有同步代码执行完成后,会从一个队列中去取出已完成的异步任务的回调加入执行栈继续执行。
4. 遇到异步任务时又交给其他线程,.....,如此循环往复。而其他异步任务完成后,将回调放入任务队列中待执行栈来取出执行。
事件循环的过程中,执行栈在同步代码执行完成后,优先检查微任务队列是否有任务需要执行,如果没有,再去宏任务队列检查是否有任务执行,如此往复。
通过不断循环去取出异步回调来执行,这个过程就是事件循环,而每一次循环就是一个事件周期或称为一次 tick。