事件循环、宏任务、微任务一网打尽(附超多经典面试题)( 二 )


  • 进入事件处理 , 执行 listener1 , 输出 listener1 。
  • 弹栈时发现JS调用栈非空(button.click函数还在运行)
  • 执行 listener2 , 输出 listener2 。
  • 弹栈时发现JS调用栈为空 , 这时候就会执行 Microtasks 队列中的所有 Microtask , 输出 promise resolved1、 promise resolved2 。
  • 4.调试V8源码的微任务
    使用工具 , chrome://tracing/ 是一个 structural profiler 或叫 CPU profiler , 与 Chrome Devtool performance 的 sample profiler 不同 , 他是由代码中主动的去埋点打印出来的 , 所以每一次函数调用都会被记录下来 , 不会像sample profiler一样漏掉采样时刻之间的状态 。 具体使用步骤可自行谷歌;
    5.任务队列和回调函数的区别
    (1)Javascript单线程任务被分为同步任务和异步任务同步任务会在调用栈中按照顺序等待主线程依次执行 , 异步任务会在异步任务有了结果后 , 将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空) , 被读取到栈内等待主线程的执行 。 (2)异步任务都能注册回调函数比如nodejs的setImmediate、MessageChannel、setTimeout、setInterval、process.nextTick 、new Promise.the(回调) 、 MutationObserver等等(3)任务队列分为:宏任务队列 , 微任务队列;
    6.settimeout、setinterval的几个注意点:
    (1)当前任务执行时间过久 , 会影响定时器任务的执行下面这个例子会有两种结果:settimeout(a, 3000); …同步代码执行很久;再一个 settimeout(b, 1000)同步代码执行时间 <= 3000 , 顺序执行 , 先b再a;可以把同步看做很快执行完;同步代码执行时间 > 3000执行完后 , 先a再b;(2)chrome中最低延时是 1ms ;即设置0最低为1ms;因为设置0的话 , 可能会导致JS单进程event loop过度循环 , 阻塞;(3)setTimeout 存在嵌套调用chrome中超过5层 , 系统会设置最短时间间隔为 4 毫秒 , setinterval是10毫秒;最开始是1ms , 太低会导致计算机没法进入睡眠模式 , 耗电非常快 , 所以改成4ms;(4)未激活的页面 , setTimeout 执行最小间隔是 1000 毫秒 , 减少加载损耗 , 节约电量;(5)延时执行时间有最大值32 个 bit 来存储延时值的 , 最大只能存放的数字是 2147483647 毫秒 , 超过这个值会溢出 , 相当于延时值被设置为 0 了 , 这导致定时器会被立即执行 。 (6)第一个参数除了可以传函数 , 还可以直接传递 code字符串, 下面一个例子setTimeout(1)和setTimeout(2)的区别首先语法如下:
    1)返回的timeoutID不一样2)code值不一样 , 一个传入1一个传入2;注意code是delay毫秒之后编译和执行的字符串 , 不推荐 , 跟eval一样有安全风险;3)执行时间不一样 , 虽然都没有设置delay , 默认0ms , 但是都要放到任务队列排队等待被执行;有先后顺序;