学习Vue3 第三十五章(event loop 和 nextTick)

lxf2024-04-04 04:05:26

  在我们学习nextTick 之前需要先了解Event Loop 事件循环机制

  在我们学js 的时候都知道js 是单线程的如果是多线程的话会引发一个问题在同一时间同时操作DOM 一个增加一个删除JS就不知道到底要干嘛了,所以这个语言是单线程的但是随着HTML5到来js也支持了多线程webWorker 但是也是不允许操作DOM

  单线程就意味着所有的任务都需要排队,后面的任务需要等前面的任务执行完才能执行,如果前面的任务耗时过长,后面的任务就需要一直等,一些从用户角度上不需要等待的任务就会一直等待,这个从体验角度上来讲是不可接受的,所以中就出现了异步的概念。

  代码从上到下按顺序执行

  script(整体代码)、setTimeout、setInterval、UI交互事件、postMessage、Ajax

  Promise.then catch finally、MutaionObserver、process.nextTick(Node.js 环境)

  运行机制

  所有的同步任务都是在主进程执行的形成一个执行栈,主线程之外,还存在一个"任务队列",异步任务执行队列中先执行宏任务,然后清空当次宏任务中的所有微任务,然后进行下一个tick如此形成循环。

   就是创建一个异步任务,那么它自然要等到同步任务执行完成后才执行。

  源码地址 corepackages untime-coresrcscheduler.ts

  nextTick 接受一个参数fn(函数)定义了一个变量P 这个P最终返回都是Promise,最后是return 如果传了fn 就使用变量P.then执行一个微任务去执行fn函数,then里面this 如果有值就调用bind改变this指向返回新的函数,否则直接调用fn,如果没传fn,就返回一个promise,最终结果都会返回一个promise在我们之前讲过的ref源码中有一段 triggerRefValue  他会去调用 triggerEffects

  那么scheduler 这个函数从哪儿来的 我们看这个类 ReactiveEffect

  scheduler 作为一个参数传进来的

  他是在初始化 effect 通过 queueJob 传进来的

   queueJob 维护job列队 并且调用  queueFlush

  queueFlush 给每一个队列创建了微任务

  例如我们显示器是60FPS

  那浏览器绘制一帧就是1000 / 60  ≈ 16.6ms

  那浏览器这一帧率做了什么

  1.处理用户的事件,就是event 例如 click,input change 等。

  2.执行定时器任务

  3.执行 requestAnimationFrame

  4.执行dom 的回流与重绘

  5.计算更新图层的绘制指令

  6.绘制指令合并主线程 如果有空余时间会执行

  所以 一个Tick 就是去做了这些事