在仓库的actions选项的动作函数中,可以包含异步操作,例如以下actionA()动作函数会异步提交someMutation()更新函数。
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
以下代码在一个组件的方法忠派发actionA()动作函数。
this.$store.dispatch('actionA').then(() => {
// 当actionA()动作函数中的异步操作执行完毕后,再执行then()函数指定的操作
…
})
在仓库的一个动作函数中还可以派发另一个动作函数:
actions: {
//…
actionB ({ dispatch, commit }) { //actionB()函数派发actionA()函数
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
此外,还可以通过async/await执行异步操作,例如:
//假定getData()和getOtherData()返回Promise对象
actions: {
async actionA ({ commit }) { //async表明当前函数包含异步操作
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') //等待actionA()的异步操作执行完毕
commit('gotOtherData', await getOtherData())
}
}
1、异步动作范例
以下位于src/main.js中的代码创建了一个包含actions选项的仓库store,包括addQuantityAction()和calculateAction()动作函数。
const store = createStore({
state () {
return {
item: {
name: '苹果',
price: 3.8,
quantity: 1,
total : 3.8
}
}
},
mutations: {
addQuantity(state){ //增加购买数量
state.item.quantity++
},
calculate(state){ //计算总价格
state.item.total=state.item.price * state.item.quantity
}
},
actions: {
addQuantityAction({commit}){
return new Promise((resolve)=>{
setTimeout( //模拟异步操作
()=>{
commit('addQuantity')
resolve()
},2000)
})
},
calculateAction({commit,dispatch}){
//等购买数量增加后,再计算总价格
dispatch('addQuantityAction').then( ()=>{
commit('calculate')
})
}
}
})
以上代码中的动作函数的作用如下。
(1)addQuantityAction()动作函数:包含异步操作,过2秒后提交addQuantity()更新函数。
(2)calculateAction()动作函数:会派发addQuantityAction()动作函数,等到addQuantityAction()动作函数的异步操作执行完毕以后,再执行then()函数,从而提交calculate()更新函数。
例程1的AsyncJudge.vue定义了AsyncJudge组件,它的calculate()方法会向仓库派发calculateAction()动作函数。
■ 例程1 AsyncJudge.vue
<template>
<div>
<p>商品名字: {{item.name}} </p>
<p>单价: {{item.price}} </p>
<p>数量: {{item.quantity}}
<button @click="calculate">增加</button> </p>
<p>总价:{{item.total}}</p>
</div>
</template>
<script>
import { mapState,mapActions } from 'vuex'
export default {
computed: mapState(['item']),
methods: {
...mapActions({calculate: 'calculateAction'})
}
}
</script>
在src/router/index.js中,为AsyncJudge组件设置的路由的路径为judge。通过浏览器访问http://localhost:8080/#/judge,会出现如图1所示的网页。在网页上单击“增加”按钮,就会看到在延迟2秒后,{{item.quantity}}及{{item.total}}的取值会发生相应的更新。
■ 图1 AsyncJudge组件的页面
2、使用async/await的范例
以下位于src/main.js中的代码创建了一个包含actions选项的仓库store,包括一个loadCustomerAction()动作函数,该动作函数用async标识,表明是包含异步操作的函数。
const store = createStore({
state () {
return {
customer: '',
msg: ''
}
},
mutations: {
clearCustomer(state){
state.msg='正在查询...'
state.customer=''
},
loadCustomer(state,response){
if(response.data !== null){
state.customer=response.data
state.msg=''
}else
state.msg='未找到匹配的数据!'
}
},
actions: {
async loadCustomerAction({commit},id){
commit('clearCustomer')
const response=await axios({
baseURL: 'http://www.javathinker.net',
url: '/customer',
method: 'get',
params: {id: id}
})
commit('loadCustomer',response)
}
}
})
loadCustomerAction()动作函数会通过Axios请求访问服务器,查询与id匹配的customer对象。在异步调用axios()函数之前,会提交clearCustomer()更新函数,等到Axios的异步请求执行完毕,再提交loadCustomer()更新函数。
例程2的AsyncCustomer.vue定义了AsyncCustomer组件。它的getCustomer()方法会向仓库派发loadCustomerAction()动作函数。
■ 例程2 AsyncCustomer.vue
<template>
<div>
<p>输入id: <input v-model="id" />
<button @click="getCustomer">查询</button> {{msg}}
</p>
<p>{{customer}}</p>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data(){ return {id: '' }},
computed: mapState(['customer','msg']),
methods: {
getCustomer(){
this.$store.dispatch('loadCustomerAction',this.id).then(
()=>{console.log(this.customer)}
)
}
}
}
</script>
在src/router/index.js中,为AsyncCustomer组件设置的路由的路径为cust。通过浏览器访问http://localhost:8080/#/cust,会出现如图2所示的网页。在网页上的id输入框输入1,再单击“查询”按钮,会看到网页先显示“正在查询...”,延迟一段时间后,再显示id为1的customer对象的信息。
■ 图2 AsyncCustomer组件的页面