浏览器--事件循环 Event Loop

94 阅读1分钟
  • 浏览器的 GPU 进程包含多条线程:

GUI 渲染线程与 JS 引擎线程是互斥的,为防止 DOM 渲染不一致,其中一个线程执行时另一个线程会被挂起。

  • GUI 渲染线程
  • JS 引擎线程
  • 事件触发线程(和 Event Loop 密切相关)
  • 定时触发线程
  • 异步 HTTP 请求线程
  • JS 引擎线程(主线程)处理同步任务,形成一个执行栈;事件触发线程处理异步任务,把异步任务的结果作为事件放入任务队列。 执行栈中的同步任务执行完毕,系统就会读取任务队列,如果有异步任务需要执行,将其加到主线程的执行栈并执行相应的异步任务。

  • 任务类型:

  • 宏任务:script (主代码块)、setTimeout 、setInterval 、setImmediate 、I/O 、UI rendering
  • 微任务:process.nextTick(Nodejs) 、promise 、Object.observe (已废弃)、MutationObserver
  • 宏任务是每次执行栈执行的代码,微任务是执行宏任务过程中产生的代码,一个宏任务执行完毕后立即执行它产生的微任务。

  • 一个宏任务及其产生的微任务执行完毕后,JS 引擎线程挂起,GUI 渲染线程执行。渲染完毕后,GUI 渲染线程挂起,JS 引擎线程执行下一个宏任务。

  • 示例代码:

    console.log('main1');
    
    process.nextTick(function() {
        console.log('process.nextTick1');
    });
    
    setTimeout(function() {
        console.log('setTimeout');
        process.nextTick(function() {
            console.log('process.nextTick2');
        });
    }, 0);
    
    new Promise(function(resolve, reject) {
        console.log('promise');
        resolve();
    }).then(function() {
        console.log('promise then');
    });
    
    console.log('main2');
    
  • 运行结果:

    main1
    promise
    main2
    process.nextTick1
    promise then
    setTimeout
    process.nextTick2