本文是在对action的理解的基础上,的进一步理解,如果你还没有看Action建议移步:
https://vuex.vuejs.org/zh/guide/
https://juejin.im/post/5abb5419f265da23a22929c2
一、Action 通常是异步的,那么如何知道 action 什么时候结束呢?更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()//promise的内部方法,返回Promise
}, 1000)
})
}
}
Promise.resolve()//promise的内部方法,返回一个Promise对象,这样才能继续执行then后续操作,源码中,action 的注册比 mutation 多了一步,那就是将函数做一些处理,并将值返回,如果你要在原基础上封装,也需要进行resolve
以下Action源码:
function registerAction (store, type, handler, path = []) {
const entry = store._actions[type] || (store._actions[type] = [])
const { dispatch, commit } = store
entry.push(function wrappedActionHandler (payload, cb) {
let res = handler({
dispatch,
commit,
getters: store.getters,
state: getNestedState(store.state, path),
rootState: store.state
}, payload, cb)
if (!isPromise(res)) {
res = Promise.resolve(res)
}
return res
})
}
这里主要是看的isPromise函数,它的主要作用是判断是否返回值是Promise,如果不是promise,我们就通过reslove生成promise,然后我们才能使用then进行下一步操作,
所以我们自己封装的时候,也需要执行resolve
因为自己封装的时候,加了resolve,返回Promise,所以现在可以在原有基础上执行then函数,继续执行其他操作:
store.dispatch('actionA').then(() => {
// ...
})
在另外一个 actionB 中也可以在actionA的基础上继续封装:
actions: {
//同上,actionB的封装
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
二、利用 async / await,进一步简化
// 假设 getData() 和 getOtherData() 返回的是 Promise
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())//等待数据,执行gotData
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())//等待getOtherData执行完之后再执行gotOtherData
}
}