美文网首页
js有趣的事件循环

js有趣的事件循环

作者: 益生菌宝 | 来源:发表于2020-02-26 15:38 被阅读0次

进程&线程

  • 浏览器是多线程的,JS是单线程的(浏览器只分配一个线程来执行JS)
  • 进程大线程小:一个进程中包含多个线程,例如在浏览器中打开一个HTML页面就占用了一个进程,加载页面的时候,浏览器分配一个线程去计算DOM树,分配其它的线程去加载对应的资源文件...再分配一个线程去自上而下执行JS

同步&异步

  • 同步:在一个线程上(主栈/主任务队列)同一个时间只能做一件事情,当前事情完成才能进行下一个事情(先把一个任务进栈执行,执行完成,在把下一个任务进栈,上一个任务出栈...)

同步任务主要包含:console.log、async函数中await()方法之前的代码、Promise中的代码

  • 异步:在主栈中执行一个任务,但是发现这个任务是一个异步的操作,我们会把它移除主栈,放到等待任务队列中,此时浏览器会分配其它线程监听异步任务是否到达指定的执行时间,如果执行完成,监听者会把到达时间的异步任务重新放到主栈中执行...

宏任务(Tasks/Macrotasks)&微任务(Microtasks)

  • 宏任务:可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)
    浏览器为了能够使得JS内部task与DOM任务能够有序的执行,会在一个task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程如下:

task主要包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)

  • 微任务: 可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。
    所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)

microtask主要包含:Promise.then、MutaionObserver、process.nextTick(Node.js 环境)、async函数中await()方法之后的代码、Promise中的then和catch

小结:
  • 宏任务按顺序执行,浏览器会在当前任务与下一个任务之间渲染
  • 微任务也按顺序执行,执行情况有两种:
    1 只要当前没有可执行的js在栈中,它就会在每个callback回调之后执行
    2 在每一个任务执行完成,从栈中移除后

运行机制

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

流程图如下:


image.png

第一题

var p = new Promise((resolve, reject) => {
        console.log('promise 构造函数')
        setTimeout(() => {
            console.log('promise 构造函数里的定时任务')
            resolve('promise 构造函数里的定时任务的resovle结果')
        }, 2000)
 })

 p.then((res) => {
        console.log('promise then 方法')
        console.log('promise then 方法的结果: ', res)
  })

 setTimeout(() => {
        console.log('定时任务')
  }, 0)

结果:

promise 构造函数
定时任务
promise 构造函数里的定时任务
promise then 方法
promise then 方法的结果:  promise 构造函数里的定时任务的resovle结果

第二题

var p = new Promise((resolve, reject) => {
        console.log('promise 构造函数')
        setTimeout(() => {
            console.log('promise 构造函数里的定时任务')
            resolve('promise 构造函数里的定时任务的resovle结果')
        }, 1)
 })

 p.then((res) => {
        console.log('promise then 方法')
        console.log('promise then 方法的结果: ', res)
  })

 setTimeout(() => {
        console.log('定时任务')
  }, 0)

结果:

promise 构造函数
promise 构造函数里的定时任务
promise then 方法
promise then 方法的结果:  promise 构造函数里的定时任务的resovle结果
定时任务

第三题

async function a1 () {
    console.log('a1 start')
    await a2()
    console.log('a1 end')
}
async function a2 () {
    console.log('a2')
}

console.log('script start')

setTimeout(() => {
    console.log('setTimeout')
}, 0)

Promise.resolve().then(() => {
    console.log('promise1')
})

a1()

let promise2 = new Promise((resolve) => {
    resolve('promise2.then')
    console.log('promise2')
})

promise2.then((res) => {
    console.log(res)
    Promise.resolve().then(() => {
        console.log('promise3')
    })
})
console.log('script end')

结果:

script start
a1 start
a2
promise2
script end
promise1
a1 end
promise2.then
promise3
setTimeout

参考博文:
英文文章:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
简书文章:https://www.jianshu.com/p/9644f13568c0

相关文章

  • js有趣的事件循环

    进程&线程 浏览器是多线程的,JS是单线程的(浏览器只分配一个线程来执行JS) 进程大线程小:一个进程中包含多个线...

  • js事件循环

    js 是单线程的, js 的异步事件就是依赖于事件循环机制 事件循环 首先,我们来解释下事件循环是个什么东西: 就...

  • 2019-03-28

    JS 事件循环机制 - 任务队列、web API、JS主线程的相互协同 这篇文章的核心是分析js的事件循环,在此我...

  • Vue源码分析—响应式原理(四)

    nextTick JS 运行机制 JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤: 所有同...

  • node 事件

    1、事件 1.1普通事件的使用 1.2、Node.js 的事件循环机制解析 1)Node 由事件循环开始,到事件循...

  • Js事件循环

    列表 JavaScript事件循环 测试金字塔 stub JavaScript事件循环理解 javaScript语...

  • js事件循环

    js是单线程的,那么是否代表参与js执行过程的线程只有一个? 答案:不是的,一共有4个线程参与该过程,但是永远只有...

  • js 事件循环

    先上代码 执行栈与事件队列 当javascript代码执行的时候会将不同的变量存于内存中的不同位置:堆(heap)...

  • js事件循环

    在js代码中,除了同步代码,就是异步代码,一个js文件是从上往下执行,遇到ajax,点击事件。settimeout...

  • JS事件循环

    深入理解javascript中的事件循环 (1)JS为何设计为单线程 js设计为单线程还是跟他的用途有关 试想一下...

网友评论

      本文标题:js有趣的事件循环

      本文链接:https://www.haomeiwen.com/subject/qhlxchtx.html