nextTick相关问题

2023-11-16

nextTick引出的问题

任务类型

JS中有两种任务类型:微任务(microtask)和宏任务(macrotask),在ES6中,microtask称为 jobs,macrotask称为 task。
宏任务: script (主代码块)、setTimeout 、setInterval 、setImmediate 、I/O 、UI rendering
微任务:process.nextTick(Nodejs) 、promise 、Object.observe 、MutationObserver

它们之间区别如下:

宏任务是每次执行栈执行的代码(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)
浏览器为了能够使得JS引擎线程与GUI渲染线程有序切换,会在当前宏任务结束之后,下一个宏任务执行开始之前,对页面进行重新渲染(宏任务 > 渲染 > 宏任务 > …)
微任务是在当前宏任务执行结束之后立即执行的任务(在当前 宏任务执行之后,UI渲染之前执行的任务)。微任务的响应速度相比setTimeout(下一个宏任务)会更快,因为无需等待UI渲染。
当前宏任务执行后,会将在它执行期间产生的所有微任务都执行一遍。

根据事件循环机制,重新梳理一下流程:

执行一个宏任务(首次执行的主代码块或者任务队列中的回调函数)
执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
宏任务执行完毕后,立即执行当前微任务队列中的所有任务(依次执行)
JS引擎线程挂起,GUI线程执行渲染
GUI线程渲染完毕后挂起,JS引擎线程执行任务队列中的下一个宏任务

VUE各版本的nextTick(截止最新的2.6.11)

因为宏任务对渲染性能的影响以及微任务的优先级过高在事件冒泡等情况下会有问题等因素,源码关于nextTick的实现有多次改动。

2.4版本之前 微任务
(Promise/MutationObserver)

2.4之后出现过如下顺序,宏任务(V.2.5.0)

  1. setImmediate(only ie10+)
  2. MessageChannel
  3. Promise
  4. setTimeout

2.5之后(可选使用宏任务或者微任务,默认使用微任务)(V2.5.22)

宏任务:

  1. setImmediate(only ie10+)
  2. MessageChannel
  3. setTimeout

微任务

  1. promise (若环境不支持promise,则使用宏任务)

2.6之后的顺序 (微任务)

  1. promise
  2. MutationObserver
  3. setImmediate
  4. setTimeout

查看 【V2.6.11】版本的源码

/* @flow */
/* globals MutationObserver */

import { noop } from 'shared/util'
import { handleError } from './error'
import { isIE, isIOS, isNative } from './env'

export let isUsingMicroTask = false

const callbacks = []
let pending = false

function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

// Here we have async deferring wrappers using microtasks.
// In 2.5 we used (macro) tasks (in combination with microtasks).
// However, it has subtle problems when state is changed right before repaint
// (e.g. #6813, out-in transitions).
// Also, using (macro) tasks in event handler would cause some weird behaviors
// that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).
// So we now use microtasks everywhere, again.
// A major drawback of this tradeoff is that there are some scenarios
// where microtasks have too high a priority and fire in between supposedly
// sequential events (e.g. #4521, #6690, which have workarounds)
// or even between bubbling of the same event (#6566).
let timerFunc

// The nextTick behavior leverages the microtask queue, which can be accessed
// via either native Promise.then or MutationObserver.
// MutationObserver has wider support, however it is seriously bugged in
// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
// completely stops working after triggering a few times... so, if native
// Promise is available, we will use it:
/* istanbul ignore next, $flow-disable-line */
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    // In problematic UIWebViews, Promise.then doesn't completely break, but
    // it can get stuck in a weird state where callbacks are pushed into the
    // microtask queue but the queue isn't being flushed, until the browser
    // needs to do some other work, e.g. handle a timer. Therefore we can
    // "force" the microtask queue to be flushed by adding an empty timer.
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  // PhantomJS and iOS 7.x
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  // Use MutationObserver where native Promise is not available,
  // e.g. PhantomJS, iOS7, Android 4.4
  // (#6466 MutationObserver is unreliable in IE11)
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  // Fallback to setImmediate.
  // Technically it leverages the (macro) task queue,
  // but it is still a better choice than setTimeout.
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  // Fallback to setTimeout.
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

export function nextTick (cb?: Function, ctx?: Object) {
  let _resolve
  callbacks.push(() => {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')
      }
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
  if (!pending) {
    pending = true
    timerFunc()
  }
  // $flow-disable-line
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}

参考资料:

https://juejin.im/post/5ae3f0956fb9a07ac90cf43e

https://juejin.im/post/5cd9854b5188252035420a13

https://www.jianshu.com/p/4f07ef18b5d7

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nextTick相关问题 的相关文章

  • vue3 vue-router 钩子函数

    全局路由守卫 vue router4 0中将next取消了 可写可不写 return false取消导航 undefined或者是return true验证导航通过 router beforeEach to from gt next是可选参
  • Vue如何将数据显示在页面中

    如何将data的数据显示在页面中 1 文本插值 div msg div 渲染结果 div hello world div 2 原始HTML插值 v html v text 区别 v text不会对标签进行转义而v html会对标签进行一次转
  • vue3使用import.meta.env在vite.config.ts下使用env环境变量的方法

    vue3使用import meta env在vite config ts下使用env环境变量的方法 编程一枚的博客 CSDN博客
  • Vue + Element UI 前端篇(十一):第三方图标库

    Vue Element UI 实现权限管理系统 前端篇 十一 第三方图标库 使用第三方图标库 用过Elment的同鞋都知道 Element UI提供的字体图符少之又少 实在是不够用啊 幸好现在有不少丰富的第三方图标库可用 引入也不会很麻烦
  • 5 款最棒的 Vue 移动端 UI 组件库 - 特别针对国内使用场景推荐

    本文完整版 最棒的 Vue 移动端 UI 组件库 特别针对国内使用场景推荐 Vue 移动端 UI 组件库推荐 Vant 3 有赞移动 UI 组件库 支持 Vue 3 微信小程序 支付宝小程序 Cube UI 滴滴出行移动端 UI 库 质量可
  • Vue 组件化

    什么是组件化 任何一个人处理信息的逻辑能力都是有限的 所以 当面对一个非常复杂的问题时 我们不太可能一次性搞定一大堆的内容 但是 我们人有一种天生的能力 就是将问题进行拆解 如果将一个复杂的问题 拆分成很多个可以处理的小问题 再将其放在整体
  • ip正则表达式

    var Sip rule value callback gt if 2 5 0 5 0 4 d 0 1 d 1 2 2 5 0 5 0 4 d 0 1 d 1 2 3 test value false callback new Error
  • vue父子组件通信方式哪几种

    第一种 props和 emit parent vue
  • Vue中的import from

    Vue中的import from 大家都知道 import from 是用来引入一些文件的 在vue中 可能有 js文件 json文件 vue文件 在JS和JSON文件引入的时候 往往需要写入一些 例如数组 export const a 例
  • vue发展历史简介

    基本介绍 Vue 是一套用于构建用户界面的 渐进式框架 与其它大型框架不同的是 Vue 被设计为可以自底向上逐层应用 最初它不过是个人项目 时至今日 已成为全世界三大前端框架之一 github 上拥有 17 8万 Star 领先于 Reac
  • vue实现拍照人脸识别功能带人脸选中框

    前言 实现打开摄像头 并识别人脸 实现效果 实现步骤 一 安装 1 官网下载 tracking js 的代码包官网入口 2 npm下载 执行命令 cnpm install tracking save 二 demo案例代码
  • vue动态绑定video视频src问题解决

    做个项目 视频部分需要先后台上传 然后前端页面显示 然后就遇到了视频动态获取地址的问题 一开始想着很简单 使用v model双向绑定就行了 结果试了下并不行 后面开始度娘 尝试过很多人说的 refs解决 结果并不行 虽然浏览器中看地址确实绑
  • Vue-cli3更改项目logo图标

    1 图标切成对应大小 2 图标名称后缀与vue原有图标logo名称 后缀一致 favicon ico 并替换 3 vue项目根目录下 新建 vue config js 添加下列代码 module exports pwa iconPaths
  • vue element select下拉框树形多选

    components 文件下新建 SelectTree文件 index vue SelectTree index vue
  • vue——vue-video-player插件实现rtmp直播流

    更新 flash已不可再使用 大家另寻出路吧 安装前首先需要注意几个点 vue video player插件 其实就是 video js 集成到 vue 中 所以千万不要再安装 video js 可能会出错 视频流我这个项目选择rtmp格式
  • 前端的工程化、模块化和组件化

    什么是工程化 工程化是一种思想而不是某种特定的技术 当然我们在实现项目工程化的过程中 我们也会去使用一些技术 前端工程化是使用软件工程的技术和方法来对前端的开发流程 技术 工具等进行规范化 标准化 其主要目的为了提高效率和降低成本 即提高开
  • 【vue3】elementplus日期组件英文转中文

    vue3 elementplus日期组件英文转中文 1 在main js或者main ts中加入 即可解决 import ElementPlus from element plus import element plus dist inde
  • vue_域名部署无法访问后端

    前言 目前部署的比较另类 因为服务器为 windows 目前还不是很会 nginx 所以现在就只能在服务器上安装 nodejs 然后直接使用 npm run dev 命令行的方式运行项目 遇到的坑 使用ip访问前端的时候 就可以访问 但是通
  • 黑豹程序员-字符串中查找出重复的字符串

    Collections frequency codeList element 字符串element 在codeList集合中重复的次数 List
  • Vue3 和Vue2的区别,以及钩子函数的使用

    Vue js 3 和 Vue js 2 是两个主要版本的流行前端框架 它们之间有很多区别 包括性能优化 新特性和改进的API等 以下是一些Vue 3与Vue 2之间的主要区别 以及一些示例代码来说明这些差异 1 性能优化 响应式系统 Vue

随机推荐

  • 关于使用向日葵等远程软件,关闭主机显示器后远程画面缩小的解决办法

    方法一 修改分辨率 直接在桌面上 右键 显示设置 gt gt gt 显示器分辨率 gt gt gt 改成更大的分辨率即可 当然这个方法的前提是 修改分辨率的选项是可选的而不是灰色的 并且你的鼠标可以下拉并点击到修改分辨率的选择框 方法二 修
  • 去伪存真:因果约束下的图神经网络泛化

    写在篇首 图神经网络 GNN 是在各种图数据应用上强有力的深度学习算法 其基本学习范式可以归纳为 在训练节点或图上训练图神经网络参数 然后利用训练好的图神经网络预测节点或者图的标签 保证这种学习范式有效的一个基本假设是IID假设 即训练数据
  • Linux 简介 & 启动过程

    简介 Linux 是一套免费使用和自由传播的开放源码的类 UNIX 操作系统 英文解释为 Linux is not Unix 1991 年由林纳斯 托瓦兹 Linus Torvalds 在赫尔辛基大学上学时出于个人爱好而编写的 主要受到 M
  • 当TabLayout标签太多时,Tab显示拥挤导致出现省略号显示不全

    在布局文件中改控件添加这个属性 app tabMode scrollable
  • Centos7忘记root密码怎么办,root重置密码

    忘记系统管理员密码真是件头疼的事 centos7的拯救之路如下 第一步 重启系统 按 e 进入启动文件界面后 第二步 按 拉到底部 找到linux16这一行 将ro改成rw 在这行最后面加上 init bin sh 第三步 然后按 Ctrl
  • python unittest教程_unittest最详细的教程(文末附视频资料)

    一 什么是unittest unittest是Python单元测试框架 类似于JUnit框架 unittest中有4个重要的概念 test fixture test case test suite test runner Testcase
  • Win10注册表无法保存对权限所作的更改拒绝访问

    转载 https blog csdn net qq 37674858 article details 107876060 在对系统的安全控制得越来越多的情况下 要对注册表的关键数据进行修改是件挺麻烦的事 时不时会弹出无法保存对xxxxxx权
  • 为Win12做准备?微软Win11 23H2将集成AI助手:GPT4免费用

    快科技7月18日消息 微软日前确认今年4季度推出Win11 23H2 这是Win11第二个年度更新 Win11 23H2具体有哪些功能升级 现在还不好说 但它会集成微软的Copilot 它很容易让人想到多年前的 曲别针 助手 但这次是AI技
  • canvas绘制气泡

    思路 使用Math random 函数绘制是个不同位置 大小 颜色的圆形 然后设置定时器 前一个状态用一个与画布相同颜色的背景图片进行覆盖 改变圆形的位置 每次改变都是在这张空白的背景图片上面重新进行重新绘制的过程 源码
  • mysql 5.7 驱动_这些 MySQL 调优配置,你都知道吗?

    关注我的头条号 获取更多运维相关知识 你想了解哪方面的运维知识 请评论区告诉我 我会尽快更新 MySQL 数据库 基本上运维都会接触到 而对于数据库的性能优化 想必是大家比较关注的 下面分享一些调优技巧 先决条件 安装 MySQL 版本大于
  • 【华为OD机试c++】九宫格游戏【2023 Q1 A卷

    题目描述 九宫格是一款广为流传的游戏 起源于河图洛书 游戏规则是 1到9九个数字放在3 3的格子中 要求每行 每列以及两个对角线上的三数之和都等于15 在金麻名著 射雕英雄传 中黃蓉曾给九宫格的一种解法 口诀 戴九恩一 左三右七 二四有肩
  • Fedora 18 的samba共享配置

    红色粗字体字为修改后内容 蓝色粗体字为特别注意内容 1 宿主机 windows 8 4G内存 2 虚拟机 VMware 9 0 1 3 虚拟主机 VMware下Fedora 18 1G内存 4 参考文章 参考文章 详解Fedora Samb
  • libevent源码学习(14):IO复用模型之epoll的封装

    目录 Libevent提供的epoll后端结构体 初始化epoll init 何时调用epoll init 事件添加epoll nochangelist add 何时调用epoll nochangelist add 事件删除epoll no
  • 监听DOM加载完成及改变MutationObserver应用

    什么是MutationObserver 接口提供了监视对DOM树所做更改的能力 它被设计为旧的MutationEvents功能的替代品 该功能是DOM3 Events规范的一部分 简单粗暴 就是监听DOM树的变动 那么 被代替的 Mutat
  • 牛顿法与牛顿迭代法

    文档主要分为两个部分 第一部分是对牛顿 拟牛顿方法的介绍 第二部分介绍具体的拟牛顿数值方法 pdf文档 1 非线性方程组解法 牛顿法 Newton法又称为Newton Raphson法 是采用函数的Taylor级数的前面几项来寻找方程的根
  • 数据库课程设计--人事管理系统代码

    人事管理系统 创建数据库 create database personal management system on primary name pms data 逻辑名 filename D sql server pms data mdf
  • BF算法与KMP算法

    针对串的操作 在主串s里面查找子串sub 从pos位置开始的第一个符合的子串 返回第一个字符的下标 BF算法如下 时间复杂度 O mn 当字符相等时 j i 当不等时 j需要回退到0号下标 i需要回退到之前的位置 1 int BF cons
  • 超分辨率:基于metric learning的无监督blind sr:Metric Learning based Interactive Modulation for Real-World Super

    Metric Learning based Interactive Modulation for Real World Super Resolution 1 思路介绍 关于blind sr 常规的方法是 建立各种 退化方法数据集 然后监督训
  • C语言:二维数组传参的格式(详细+总结)

    希望能帮助到你 我将无比快乐 你的点赞 是我前进的动力 初遇二维数组作函数参数 宛如自己化身为了大头儿子 很头大 不禁大声呐喊 该怎么声明定义 该怎么调用 又该怎么函数中操作元素和地址 在此 我要拨开这些问题的一些迷雾 我相信 有心人看完后
  • nextTick相关问题

    nextTick引出的问题 任务类型 JS中有两种任务类型 微任务 microtask 和宏任务 macrotask 在ES6中 microtask称为 jobs macrotask称为 task 宏任务 script 主代码块 setTi