组合Action #
Action 组合方式 #
顺序执行 #
一个 Action 完成后再执行另一个:
javascript
actions: {
async actionA({ commit }) {
const data = await api.fetchA()
commit('SET_A', data)
return data
},
async actionB({ commit, dispatch }) {
// 等待 actionA 完成
const dataA = await dispatch('actionA')
// 使用 actionA 的结果
const dataB = await api.fetchB(dataA.id)
commit('SET_B', dataB)
return { dataA, dataB }
}
}
并行执行 #
多个 Action 同时执行:
javascript
actions: {
async fetchAll({ dispatch }) {
// 并行执行
const [users, products, orders] = await Promise.all([
dispatch('fetchUsers'),
dispatch('fetchProducts'),
dispatch('fetchOrders')
])
return { users, products, orders }
},
async fetchUsers({ commit }) {
const users = await api.fetchUsers()
commit('SET_USERS', users)
return users
},
async fetchProducts({ commit }) {
const products = await api.fetchProducts()
commit('SET_PRODUCTS', products)
return products
},
async fetchOrders({ commit }) {
const orders = await api.fetchOrders()
commit('SET_ORDERS', orders)
return orders
}
}
实际应用场景 #
用户登录流程 #
javascript
actions: {
async login({ dispatch }, credentials) {
// 1. 登录
const { user, token } = await api.login(credentials)
// 2. 保存 token
await dispatch('saveToken', token)
// 3. 获取用户详细信息
await dispatch('fetchUserProfile', user.id)
// 4. 获取用户权限
await dispatch('fetchPermissions', user.id)
// 5. 获取用户通知
dispatch('fetchNotifications', user.id) // 不等待
return user
},
saveToken({ commit }, token) {
localStorage.setItem('token', token)
commit('SET_TOKEN', token)
},
async fetchUserProfile({ commit }, userId) {
const profile = await api.getUserProfile(userId)
commit('SET_PROFILE', profile)
return profile
},
async fetchPermissions({ commit }, userId) {
const permissions = await api.getUserPermissions(userId)
commit('SET_PERMISSIONS', permissions)
return permissions
},
async fetchNotifications({ commit }, userId) {
const notifications = await api.getNotifications(userId)
commit('SET_NOTIFICATIONS', notifications)
return notifications
}
}
购物车结算流程 #
javascript
actions: {
async checkout({ dispatch, state, commit }) {
commit('SET_CHECKOUT_STATUS', 'pending')
try {
// 1. 验证购物车
await dispatch('validateCart')
// 2. 验证库存
await dispatch('validateInventory')
// 3. 应用优惠
const discount = await dispatch('applyCoupon', state.couponCode)
// 4. 创建订单
const order = await dispatch('createOrder', {
items: state.items,
discount
})
// 5. 处理支付
await dispatch('processPayment', order)
// 6. 清空购物车
await dispatch('clearCart')
commit('SET_CHECKOUT_STATUS', 'success')
return order
} catch (error) {
commit('SET_CHECKOUT_STATUS', 'failed')
commit('SET_ERROR', error.message)
throw error
}
},
async validateCart({ state }) {
if (state.items.length === 0) {
throw new Error('购物车为空')
}
},
async validateInventory({ state }) {
for (const item of state.items) {
const inventory = await api.getInventory(item.productId)
if (inventory < item.quantity) {
throw new Error(`${item.name} 库存不足`)
}
}
},
async applyCoupon({ commit }, code) {
if (!code) return 0
const coupon = await api.validateCoupon(code)
commit('SET_COUPON', coupon)
return coupon.discount
},
async createOrder({ commit }, { items, discount }) {
const order = await api.createOrder({
items,
discount,
total: items.reduce((sum, item) => sum + item.price * item.quantity, 0) - discount
})
commit('SET_ORDER', order)
return order
},
async processPayment({ commit }, order) {
const payment = await api.processPayment(order)
commit('SET_PAYMENT', payment)
return payment
},
clearCart({ commit }) {
commit('CLEAR_CART')
commit('CLEAR_COUPON')
}
}
数据初始化 #
javascript
actions: {
async initApp({ dispatch, commit }) {
commit('SET_APP_READY', false)
try {
// 并行获取基础数据
await Promise.all([
dispatch('fetchCategories'),
dispatch('fetchSettings'),
dispatch('fetchTranslations')
])
// 检查登录状态
const isLoggedIn = await dispatch('checkAuth')
if (isLoggedIn) {
// 登录后获取用户数据
await Promise.all([
dispatch('fetchUserProfile'),
dispatch('fetchUserPreferences'),
dispatch('fetchNotifications')
])
}
commit('SET_APP_READY', true)
} catch (error) {
commit('SET_INIT_ERROR', error.message)
throw error
}
}
}
跨模块调用 #
调用其他模块的 Action #
javascript
// store/modules/user.js
actions: {
async login({ dispatch }, credentials) {
const user = await api.login(credentials)
// 调用 cart 模块的 action
await dispatch('cart/fetchCart', null, { root: true })
// 调用 notifications 模块的 action
await dispatch('notifications/fetchAll', null, { root: true })
return user
}
}
使用 rootState 和 rootGetters #
javascript
// store/modules/orders.js
actions: {
async createOrder({ commit, rootState, rootGetters }, orderData) {
// 访问其他模块的状态
const user = rootState.user.current
// 访问其他模块的 getter
const discount = rootGetters['user/memberDiscount']
const order = await api.createOrder({
...orderData,
userId: user.id,
discount
})
commit('ADD_ORDER', order)
return order
}
}
高级模式 #
条件执行 #
javascript
actions: {
async fetchData({ state, dispatch, commit }) {
// 如果已有数据且未过期,直接返回
if (state.data && !isExpired(state.lastFetch)) {
return state.data
}
// 否则重新获取
return dispatch('refreshData')
},
async refreshData({ commit }) {
commit('SET_LOADING', true)
try {
const data = await api.fetchData()
commit('SET_DATA', data)
commit('SET_LAST_FETCH', Date.now())
return data
} finally {
commit('SET_LOADING', false)
}
}
}
队列执行 #
javascript
const actionQueue = []
let isProcessing = false
actions: {
async queuedAction({ dispatch }, action) {
return new Promise((resolve, reject) => {
actionQueue.push({
action,
resolve,
reject
})
if (!isProcessing) {
dispatch('processQueue')
}
})
},
async processQueue({ dispatch }) {
if (actionQueue.length === 0) {
isProcessing = false
return
}
isProcessing = true
const { action, resolve, reject } = actionQueue.shift()
try {
const result = await dispatch(action.type, action.payload)
resolve(result)
} catch (error) {
reject(error)
}
// 处理下一个
await dispatch('processQueue')
}
}
事务模式 #
javascript
actions: {
async transferPoints({ commit, dispatch }, { fromUserId, toUserId, points }) {
const backup = {}
try {
// 备份当前状态
backup.fromUser = await dispatch('getUser', fromUserId)
backup.toUser = await dispatch('getUser', toUserId)
// 执行转账
await dispatch('deductPoints', { userId: fromUserId, points })
await dispatch('addPoints', { userId: toUserId, points })
// 记录交易
await dispatch('recordTransaction', { fromUserId, toUserId, points })
} catch (error) {
// 回滚
commit('SET_USER', backup.fromUser)
commit('SET_USER', backup.toUser)
throw error
}
}
}
最佳实践 #
1. 保持 Action 简洁 #
javascript
// 推荐:拆分为多个小 action
actions: {
async checkout({ dispatch }) {
await dispatch('validateCart')
await dispatch('processPayment')
await dispatch('clearCart')
}
}
// 不推荐:一个 action 做太多事
actions: {
async checkout({ commit, state }) {
// 所有逻辑都在这里...
}
}
2. 合理使用并行和顺序 #
javascript
// 可以并行的操作
await Promise.all([
dispatch('fetchUsers'),
dispatch('fetchProducts')
])
// 有依赖的操作
const user = await dispatch('fetchUser', userId)
await dispatch('fetchUserPosts', user.id)
3. 错误处理 #
javascript
actions: {
async complexOperation({ dispatch, commit }) {
commit('SET_LOADING', true)
try {
const result = await dispatch('step1')
await dispatch('step2', result)
await dispatch('step3')
commit('SET_SUCCESS', true)
} catch (error) {
commit('SET_ERROR', error.message)
throw error
} finally {
commit('SET_LOADING', false)
}
}
}
总结 #
Action 组合要点:
| 模式 | 说明 |
|---|---|
| 顺序执行 | await dispatch 依次执行 |
| 并行执行 | Promise.all 同时执行 |
| 跨模块 | 使用 |
| 条件执行 | 根据状态决定是否执行 |
继续学习 mapActions辅助函数,简化 Action 映射。
最后更新:2026-03-28