vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue 3 onMounted 同步与异步

Vue 3 onMounted 中控制同步与异步执行策略的方案详解

作者:FlyBeautySky

在Vue 3的onMounted钩子中,控制多个函数的同步和异步执行有多种方法,本文给大家分享Vue 3 onMounted 中控制同步与异步执行策略的方案,感兴趣的朋友跟随小编一起看看吧

在 Vue 3 的 onMounted 钩子中,控制多个函数的同步和异步执行有多种方法。以下是详细的技术方案:

📊 核心概念对比

执行方式特点适用场景
同步执行顺序执行,前一个完成后才开始下一个有依赖关系的操作
并行执行同时启动,等待所有完成独立的任务,提高效率
按条件执行根据条件决定是否执行条件加载、权限控制

一、同步执行控制

1.基本同步顺序执行

<script setup>
import { onMounted } from 'vue'
onMounted(() => {
  console.log('1. 开始同步执行')
  // 函数1
  const result1 = function1()
  console.log('函数1完成:', result1)
  // 函数2(依赖函数1的结果)
  const result2 = function2(result1)
  console.log('函数2完成:', result2)
  // 函数3(依赖函数2的结果)
  const result3 = function3(result2)
  console.log('函数3完成:', result3)
  console.log('所有同步函数执行完成')
})
function function1() {
  console.log('执行 function1')
  return 'function1 的结果'
}
function function2(input) {
  console.log('执行 function2,输入:', input)
  return input + ' -> 经过function2处理'
}
function function3(input) {
  console.log('执行 function3,输入:', input)
  return input + ' -> 经过function3处理'
}
</script>

输出

1. 开始同步执行
执行 function1
函数1完成: function1 的结果
执行 function2,输入: function1 的结果
函数2完成: function1 的结果 -> 经过function2处理
执行 function3,输入: function1 的结果 -> 经过function2处理
函数3完成: function1 的结果 -> 经过function2处理 -> 经过function3处理
所有同步函数执行完成

2.使用 async/await 控制异步函数同步执行

<script setup>
import { onMounted } from 'vue'
onMounted(async () => {
  console.log('🚀 开始顺序执行异步任务')
  try {
    // 1. 等待第一个异步任务完成
    const user = await fetchUserData()
    console.log('✅ 用户数据获取完成:', user.name)
    // 2. 等待第二个异步任务(依赖第一个结果)
    const orders = await fetchUserOrders(user.id)
    console.log('✅ 订单数据获取完成,数量:', orders.length)
    // 3. 等待第三个异步任务
    const analytics = await initAnalytics(orders)
    console.log('✅ 分析工具初始化完成')
    console.log('🎉 所有任务顺序执行完成')
  } catch (error) {
    console.error('❌ 执行失败:', error)
  }
})
// 模拟异步函数
async function fetchUserData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ id: 1, name: '张三' })
    }, 1000)
  })
}
async function fetchUserOrders(userId) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve([{ id: 1, product: '商品A' }, { id: 2, product: '商品B' }])
    }, 1500)
  })
}
async function initAnalytics(orders) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ events: orders.length })
    }, 500)
  })
}
</script>

执行时间:约 3 秒(1000 + 1500 + 500)

二、并行执行控制

1.使用 Promise.all 并行执行

<script setup>
import { onMounted, ref } from 'vue'
const loading = ref(true)
const data = ref({})
onMounted(async () => {
  console.log('🚀 开始并行执行任务')
  const startTime = Date.now()
  try {
    // 并行执行所有异步任务
    const [userData, configData, permissions] = await Promise.all([
      fetchUserData(),
      fetchConfigData(),
      fetchUserPermissions()
    ])
    const endTime = Date.now()
    console.log(`✅ 所有并行任务完成,耗时: ${endTime - startTime}ms`)
    // 整合数据
    data.value = { ...userData, ...configData, permissions }
    loading.value = false
    console.log('🎉 数据整合完成:', data.value)
  } catch (error) {
    console.error('❌ 并行执行失败:', error)
    loading.value = false
  }
})
async function fetchUserData() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('✅ 用户数据获取完成')
      resolve({ name: '张三', age: 25 })
    }, 2000)  // 模拟2秒延迟
  })
}
async function fetchConfigData() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('✅ 配置数据获取完成')
      resolve({ theme: 'dark', language: 'zh-CN' })
    }, 1500)  // 模拟1.5秒延迟
  })
}
async function fetchUserPermissions() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('✅ 权限数据获取完成')
      resolve(['read', 'write', 'delete'])
    }, 1000)  // 模拟1秒延迟
  })
}
</script>

输出

🚀 开始并行执行任务
✅ 权限数据获取完成
✅ 配置数据获取完成
✅ 用户数据获取完成
✅ 所有并行任务完成,耗时: 2002ms
🎉 数据整合完成: {name: '张三', age: 25, theme: 'dark', language: 'zh-CN', permissions: ['read', 'write', 'delete']}

总耗时:约 2 秒(最慢的任务耗时)

2.使用 Promise.allSettled 处理并行任务(不因失败中断)

<script setup>
import { onMounted, ref } from 'vue'
const results = ref({})
onMounted(async () => {
  console.log('🚀 开始并行执行任务(包含容错)')
  // 使用 allSettled,即使某个任务失败也不会中断
  const settledResults = await Promise.allSettled([
    fetchUserData(),
    fetchConfigData(),
    fetchUserPermissions(),
    fetchOptionalData()  // 这个可能失败
  ])
  // 处理结果
  const successResults = {}
  const failedResults = {}
  settledResults.forEach((result, index) => {
    if (result.status === 'fulfilled') {
      successResults[`task${index}`] = result.value
    } else {
      failedResults[`task${index}`] = result.reason
    }
  })
  results.value = { success: successResults, failed: failedResults }
  console.log('📊 执行结果:', results.value)
})
async function fetchUserData() {
  return Promise.resolve({ user: '张三' })
}
async function fetchConfigData() {
  return Promise.resolve({ theme: 'dark' })
}
async function fetchUserPermissions() {
  return Promise.resolve(['read', 'write'])
}
async function fetchOptionalData() {
  // 模拟可能失败的任务
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() > 0.5) {
        resolve({ optional: 'data' })
      } else {
        reject(new Error('Optional data fetch failed'))
      }
    }, 500)
  })
}
</script>

三、混合执行策略

1.分组并行 + 顺序执行

<script setup>
import { onMounted, ref } from 'vue'
const executionLog = ref([])
onMounted(async () => {
  console.log('🚀 开始混合执行策略')
  addLog('开始执行')
  try {
    // 阶段1:并行加载不依赖的数据
    addLog('阶段1: 并行加载基础数据')
    const [user, config] = await Promise.all([
      fetchUserData(),
      fetchConfigData()
    ])
    addLog('阶段1完成')
    // 阶段2:顺序执行依赖任务
    addLog('阶段2: 顺序加载依赖数据')
    const orders = await fetchUserOrders(user.id)
    addLog('订单数据加载完成')
    const analytics = await initAnalytics(orders)
    addLog('分析工具初始化完成')
    // 阶段3:并行执行最后步骤
    addLog('阶段3: 并行执行清理和通知')
    await Promise.all([
      sendAnalytics(analytics),
      updateUserLastLogin(user.id)
    ])
    addLog('阶段3完成')
    addLog('🎉 所有任务完成')
  } catch (error) {
    addLog(`❌ 执行失败: ${error.message}`)
  }
})
function addLog(message) {
  const timestamp = new Date().toLocaleTimeString()
  executionLog.value.push(`${timestamp}: ${message}`)
  console.log(message)
}
// 模拟函数
async function fetchUserData() {
  await delay(1000)
  return { id: 1, name: '张三' }
}
async function fetchConfigData() {
  await delay(800)
  return { theme: 'dark' }
}
async function fetchUserOrders() {
  await delay(1200)
  return [{ id: 1 }, { id: 2 }]
}
async function initAnalytics() {
  await delay(600)
  return { initialized: true }
}
async function sendAnalytics() {
  await delay(300)
}
async function updateUserLastLogin() {
  await delay(400)
}
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}
</script>

执行时间:约 3.6 秒(1000 + 1200 + 600 + 400)

2.带并发限制的并行执行

<script setup>
import { onMounted, ref } from 'vue'
const tasks = ref(Array.from({ length: 10 }, (_, i) => ({
  id: i + 1,
  status: 'pending',
  result: null
})))
onMounted(async () => {
  console.log('🚀 开始带并发限制的执行')
  // 并发数限制为3
  const concurrencyLimit = 3
  const taskPromises = tasks.value.map(task => task.id)
  // 分批次执行
  for (let i = 0; i < taskPromises.length; i += concurrencyLimit) {
    const batch = taskPromises.slice(i, i + concurrencyLimit)
    console.log(`执行批次 ${i / concurrencyLimit + 1}: 任务 ${batch.join(', ')}`)
    // 并行执行当前批次
    const batchPromises = batch.map(async taskId => {
      const task = tasks.value.find(t => t.id === taskId)
      task.status = 'running'
      try {
        const result = await simulateTask(taskId)
        task.status = 'completed'
        task.result = result
        console.log(`✅ 任务 ${taskId} 完成`)
      } catch (error) {
        task.status = 'failed'
        task.result = error.message
        console.log(`❌ 任务 ${taskId} 失败`)
      }
    })
    // 等待当前批次所有任务完成
    await Promise.all(batchPromises)
  }
  console.log('🎉 所有批次执行完成')
})
async function simulateTask(taskId) {
  // 模拟随机耗时任务
  const duration = 500 + Math.random() * 1000
  await delay(duration)
  // 模拟10%的失败率
  if (Math.random() < 0.1) {
    throw new Error(`任务 ${taskId} 模拟失败`)
  }
  return `任务 ${taskId} 结果,耗时 ${Math.round(duration)}ms`
}
</script>

四、高级控制模式

1.使用队列控制执行顺序

<script setup>
import { onMounted, ref } from 'vue'
class TaskQueue {
  constructor(concurrency = 1) {
    this.concurrency = concurrency
    this.running = 0
    this.queue = []
  }
  add(task) {
    return new Promise((resolve, reject) => {
      this.queue.push({ task, resolve, reject })
      this.run()
    })
  }
  run() {
    while (this.running < this.concurrency && this.queue.length) {
      const { task, resolve, reject } = this.queue.shift()
      this.running++
      task()
        .then(resolve)
        .catch(reject)
        .finally(() => {
          this.running--
          this.run()
        })
    }
  }
}
const executionOrder = ref([])
onMounted(async () => {
  console.log('🚀 使用队列控制执行顺序')
  // 创建并发数为2的队列
  const queue = new TaskQueue(2)
  // 添加任务到队列
  const tasks = [
    () => simulateTask('任务A', 1000),
    () => simulateTask('任务B', 800),
    () => simulateTask('任务C', 1200),
    () => simulateTask('任务D', 600),
    () => simulateTask('任务E', 900)
  ]
  // 记录执行顺序
  const addToOrder = (taskName) => {
    executionOrder.value.push({
      time: Date.now(),
      task: taskName
    })
  }
  // 并行执行所有任务(但限制并发数)
  const startTime = Date.now()
  addToOrder('开始执行')
  await Promise.all(tasks.map((task, index) => 
    queue.add(async () => {
      addToOrder(`开始 ${task.name}`)
      await task()
      addToOrder(`完成 ${task.name}`)
    })
  ))
  addToOrder(`全部完成,总耗时: ${Date.now() - startTime}ms`)
  console.log('📊 执行顺序:', executionOrder.value)
})
async function simulateTask(name, duration) {
  console.log(`开始执行 ${name}`)
  await delay(duration)
  console.log(`完成 ${name}`)
  return name
}
</script>

2.使用 async/await 生成器控制流程

<script setup>
import { onMounted, ref } from 'vue'
const steps = ref([])
onMounted(async () => {
  console.log('🚀 使用生成器控制执行流程')
  // 定义任务生成器
  async function* taskGenerator() {
    steps.value.push('1. 初始化')
    yield await initApp()
    steps.value.push('2. 加载用户数据')
    const user = yield await loadUserData()
    steps.value.push('3. 根据用户角色加载不同数据')
    if (user.role === 'admin') {
      yield await loadAdminData()
    } else {
      yield await loadUserSpecificData(user.id)
    }
    steps.value.push('4. 完成初始化')
    yield await finalizeInit()
  }
  // 执行生成器
  const generator = taskGenerator()
  let result = await generator.next()
  while (!result.done) {
    console.log('步骤完成:', result.value)
    result = await generator.next()
  }
  console.log('🎉 所有步骤完成')
  console.log('步骤记录:', steps.value)
})
async function initApp() {
  await delay(500)
  return '应用初始化完成'
}
async function loadUserData() {
  await delay(800)
  return { id: 1, name: '张三', role: 'admin' }
}
async function loadAdminData() {
  await delay(1000)
  return '管理员数据加载完成'
}
async function loadUserSpecificData() {
  await delay(600)
  return '用户数据加载完成'
}
async function finalizeInit() {
  await delay(300)
  return '初始化完成'
}
</script>

五、错误处理与重试机制

1.带重试的异步执行

<script setup>
import { onMounted, ref } from 'vue'
const attempts = ref({})
onMounted(async () => {
  console.log('🚀 开始带重试机制的执行')
  // 重试配置
  const retryConfig = {
    maxRetries: 3,
    retryDelay: 1000,
    onRetry: (taskName, attempt) => {
      console.log(`🔄 ${taskName} 第 ${attempt} 次重试`)
    }
  }
  // 执行带重试的任务
  const result = await executeWithRetry(
    fetchCriticalData,
    ['关键数据'],
    retryConfig
  )
  console.log('📊 最终结果:', result)
})
// 重试执行器
async function executeWithRetry(task, args, config) {
  const { maxRetries, retryDelay, onRetry } = config
  let lastError
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      if (attempt > 0 && onRetry) {
        onRetry(task.name, attempt)
      }
      attempts.value[task.name] = (attempts.value[task.name] || 0) + 1
      return await task(...args)
    } catch (error) {
      lastError = error
      console.log(`❌ ${task.name} 第 ${attempt} 次失败:`, error.message)
      if (attempt < maxRetries) {
        await delay(retryDelay)
      }
    }
  }
  throw lastError
}
// 模拟可能失败的任务
async function fetchCriticalData() {
  const shouldFail = Math.random() < 0.7  // 70%失败率
  await delay(300)
  if (shouldFail) {
    throw new Error('网络请求失败')
  }
  return { data: '重要数据' }
}
</script>

六、最佳实践总结

同步执行场景

// 适用于有依赖关系的任务
onMounted(async () => {
  const data1 = await task1()      // 必须先完成
  const data2 = await task2(data1) // 依赖data1
  const data3 = await task3(data2) // 依赖data2
})

并行执行场景

// 适用于独立任务,提高效率
onMounted(async () => {
  const [result1, result2, result3] = await Promise.all([
    task1(),  // 独立任务
    task2(),  // 独立任务
    task3()   // 独立任务
  ])
})

混合执行场景

// 组合使用,先并行后顺序
onMounted(async () => {
  // 并行加载基础数据
  const [user, config] = await Promise.all([
    fetchUser(),
    fetchConfig()
  ])
  // 顺序处理依赖数据
  const orders = await fetchOrders(user.id)
  await processOrders(orders)
  // 最后并行清理
  await Promise.all([
    sendAnalytics(),
    updateCache()
  ])
})

错误处理最佳实践

onMounted(async () => {
  try {
    // 主任务
    await mainTask()
  } catch (error) {
    console.error('主任务失败:', error)
    // 降级处理
    await fallbackTask()
  } finally {
    // 清理资源
    await cleanup()
  }
})

性能监控

onMounted(async () => {
  const startTime = performance.now()
  // 执行任务
  await yourTasks()
  const endTime = performance.now()
  console.log(`⏱️ 执行耗时: ${Math.round(endTime - startTime)}ms`)
  // 可以发送到监控系统
  if (endTime - startTime > 2000) {
    console.warn('⚠️ 执行时间过长')
  }
})

🎯 核心要点

  1. 使用 await 控制顺序执行
  2. 使用 Promise.all() 控制并行执行
  3. 使用 Promise.allSettled() 处理可能失败的任务
  4. 合理组合顺序和并行执行优化性能
  5. 实现适当的错误处理和重试机制
  6. 使用队列控制并发数,避免资源耗尽

通过合理选择执行策略,可以显著优化组件初始化的性能和用户体验。

到此这篇关于Vue 3 onMounted 中控制同步与异步执行策略的方案详解的文章就介绍到这了,更多相关Vue 3 onMounted 同步与异步内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文