watch-代码片段

watch-代码片段

1.代码

记录下一段代码

javascript 复制代码
<script setup>
import { ref, watch } from 'vue'

const id = ref(1)
let currentRequestId = 0

// 模拟异步请求
function fetchData(requestId, newId) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ id: newId, data: `Data for ID ${newId}` })
    }, 1000) // 模拟 1 秒的网络延迟
  })
}

watch(id, async (newId, oldId) => {
  console.log(`ID changed from ${oldId} to ${newId}`)
  
  const requestId = ++currentRequestId
  
  try {
    const result = await fetchData(requestId, newId)
    
    // 检查这个请求是否仍然是最新的
    if (requestId === currentRequestId) {
      console.log('Request completed with latest ID:', result)
    } else {
      console.log('Request completed, but ID has changed. Discarding result.')
    }
  } catch (error) {
    console.error('Error fetching data:', error)
  }
})

// 模拟 ID 变化
setTimeout(() => { id.value = 2 }, 500)
setTimeout(() => { id.value = 3 }, 1500)
</script>

<template>
  <div>
    <p>Current ID: {{ id }}</p>
  </div>
</template>

这段代码记录下,

  1. 初始化阶段:

    javascript 复制代码
    const id = ref(1)
    let currentRequestId = 0
    • id 被初始化为响应式引用,值为1。
    • currentRequestId 初始化为0。
  2. 设置 watch 函数:

    javascript 复制代码
    watch(id, async (newId, oldId) => { ... })
    • Vue设置了一个观察器,监听 id 的变化。
    • 此时,watch函数还未执行,只是被定义和注册。
  3. 设置定时器:

    javascript 复制代码
    setTimeout(() => { id.value = 2 }, 500)
    setTimeout(() => { id.value = 3 }, 1500)
    • 两个定时器被添加到事件队列中。
  4. 主线程执行完毕,进入事件循环。

  5. 500ms后:

    • 第一个定时器触发。
    • id.value 被设置为2。
    • 这触发了 watch 函数。
  6. Watch 函数第一次执行:

    • currentRequestId 增加到1。
    • fetchData(1, 2) 被调用,返回一个Promise。
    • 这个Promise被添加到微任务队列。
  7. 1000ms后(自步骤5开始):

    • fetchData 的定时器触发。
    • Promise 解析,结果添加到微任务队列。
  8. 1500ms后(自开始):

    • 第二个定时器触发。
    • id.value 被设置为3。
    • 这再次触发了 watch 函数。
  9. Watch 函数第二次执行:

    • currentRequestId 增加到2。
    • fetchData(2, 3) 被调用,返回另一个Promise。
  10. 微任务队列处理:

    • 第一个 fetchData 的结果被处理。
    • 但是 requestId (1) !== currentRequestId (2),所以结果被丢弃。
  11. 2500ms后(自开始):

    • 第二个 fetchData 的定时器触发。
    • Promise 解析,结果添加到微任务队列。
  12. 微任务队列再次处理:

    • 第二个 fetchData 的结果被处理。
    • 这次 requestId (2) === currentRequestId (2),所以结果被接受。

这个过程展示了JavaScript的异步特性和事件循环机制。通过使用 currentRequestId,我们能够跟踪最新的请求,并确保只处理最新ID对应的数据,即使在多个异步操作并发执行的情况下也能正确工作。

相关推荐
caimouse4 分钟前
MM 学习笔记 10:页面文件与系统加载器
笔记·学习·reactos
一只小菜鸡..9 分钟前
南京大学 操作系统 (JYY) 学习笔记:Hello, OS World! (程序的机器视角)
java·笔记·学习
不好听61320 分钟前
React 父子组件通信:从 Todo 应用理解单向数据流
前端·react.js
光影少年23 分钟前
RN 路由栈管理、页面销毁、返回拦截
javascript·react native·react.js
_lucas28 分钟前
做了一个glsl在线调试工具
前端·javascript·three.js
lazy H1 小时前
从入门到日常开发,一篇文章掌握 Git 核心操作
git·后端·学习·github
To_OC9 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
腻害兔9 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
不好听6139 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus9 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端