js事件循环机制 (Event Loop)

1、JavaScript是单线程单并发语言

  • 什么是单线程javascript

    主程序只有一个线程,即同一时间片段内其只能执行单个任务。java

  • 为何选择单线程?git

    JavaScript的主要用途是与用户互动,以及操做DOM。这决定了它只能是单线程,不然会带来很复杂的同步问题。github

  • 单线程意味着什么?promise

    单线程就意味着,全部任务都须要排队,前一个任务结束,才会执行后一个任务。若是前一个任务耗时很长,后一个任务就须要一直等着。这就会致使IO操做(耗时但cpu闲置)时形成性能浪费的问题。浏览器

  • 如何解决单线程带来的性能问题?并发

    答案是异步!主线程彻底能够无论IO操做,暂时挂起处于等待中的任务,先运行排在后面的任务。等到IO操做返回告终果,再回过头,把挂起的任务继续执行下去。因而,全部任务能够分红两种,一种是同步任务(synchronous),另外一种是异步任务(asynchronous)异步

    注: 当主线程阻塞时,任务队列仍然是可以被推入任务的async

2、事件循环Event Loop

一、JavaScript 内存模型图oop

 

二、JavaScript 代码执行机制

  • 全部同步任务都在主线程上的栈中执行。

  • 主线程以外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

  • 一旦"栈"中的全部同步任务执行完毕,系统就会读取"任务队列",选择出须要首先执行的任务(由浏览器决定,并不按序)。

三、事件循环(EventLoop)

 

3、异步任务

1.MacroTask(宏观Task) setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering

2.MicroTask(微观任务) process.nextTick, Promise, Object.observe, MutationObserver

规范:

  • 每一个浏览器环境,至多有一个event loop。
  • 一个event loop能够有1个或多个MacroTask queue,而仅有一个 MicroTask Queue。
  • 一个task queue是一列有序的task, 每一个task定义时都有一个task source,从同一个task source来的task必须放到同一个task queue,从不一样源来的则被添加到不一样队列。
  • tasks are scheduled,因此浏览器能够从内部到JS/DOM,保证动做按序发生。
  • Microtasks are scheduled,Microtask queue 在当前 task queue 的结尾执行。microtask中添加的microtask也被添加到Microtask queue的末尾并处理。

    注: event loop的每一个turn,是由浏览器决定先执行哪一个task queue。这容许浏览器为不一样的task source设置不一样的优先级,好比为用户交互设置更高优先级来使用户感受流畅。

4、实例

```javascript

function ELoop() { // 当前任务 let p = new Promise((resolve, reject) => { console.log("current Task") resolve(); }); let nextP;

setTimeout(() => {
        console.log("MacroTask_1");
        nextP.then(() => {
            // 第一次执行时,这段代码并无执行到。
            console.log("MicroTask_promise_1"); //第一个MicroTask
        })
        console.log("MacroTask_1 end")
    }, 0) // 第一个 MacroTask

    setTimeout(() => {
        console.log("MacroTask_2");
        console.log("MacroTask_2 end")
    }, 0) // 第二个MacroTask

    nextP = p.then(() => {
        console.log("MicroTask_promise_2"); //第一个MicroTask
    }).then(() => {
        console.log("MicroTask_promise_3"); // 第二个MicroTask
    })

    console.log("current Task end")
}

ELoop();

/**输出结果:
current Task
current Task end
MicroTask_promise_2
MicroTask_promise_3
MacroTask_1
MacroTask_1 end
MicroTask_promise_1
MacroTask_2
MacroTask_2 end
**/

```

github:https://github.com/Hasyou99/Daily-summary

相关文章
相关标签/搜索