Answers:
actions
在Vuex中是异步的。让调用函数(动作的发起者)知道某个动作已完成的唯一方法是返回一个Promise,然后再解决它。
这是一个示例:myAction
返回Promise
,进行http调用,然后解析或拒绝Promise
后者-全部异步
actions: {
myAction(context, data) {
return new Promise((resolve, reject) => {
// Do something here... lets say, a http call using vue-resource
this.$http("/api/something").then(response => {
// http success, call the mutator and change something in state
resolve(response); // Let the calling function know that http is done. You may send some data back
}, error => {
// http failed, let the calling function know that action did not work out
reject(error);
})
})
}
}
现在,当您的Vue组件启动时myAction
,它将获得此Promise对象,并且可以知道它是否成功。这是Vue组件的一些示例代码:
export default {
mounted: function() {
// This component just got created. Lets fetch some data here using an action
this.$store.dispatch("myAction").then(response => {
console.log("Got some data, now lets show something in this component")
}, error => {
console.error("Got nothing from server. Prompt user to check internet connection and try again")
})
}
}
正如您在上面看到的,actions
返回极有帮助Promise
。否则,动作发起者无法知道正在发生的事情以及什么时候情况稳定到足以在用户界面上显示某些内容。
最后一个注意事项mutators
-正如您正确指出的那样,它们是同步的。它们会更改中的内容,state
通常称为actions
。有没有必要混合Promises
使用mutators
,作为actions
手柄部分。
编辑:我对单向数据流的Vuex周期的看法:
如果您像访问this.$store.state["your data key"]
组件中那样访问数据,则数据流是单向的。
行动的承诺只是让组件知道行动已完成。
在上面的示例中,该组件可以从promise resolve函数获取数据(非单向,因此不建议使用),也可以直接从$store.state["your data key"]
单向获取,并遵循vuex数据生命周期。
上面的段落假定您的mutator使用Vue.set(state, "your data key", http_data)
,一旦您的操作中完成http调用。
Promise.reject()
。
failed
set 的mutator,state.foo.failed = true
组件可以处理。为此,无需将承诺传递给组件,而且,作为奖励,任何其他想对同一故障做出反应的其他事情也可以从商店中进行。
{isLoading:true}
我的州那样的中间价值观,因此诉诸于Promises。您的偏好可能会有所不同。归根结底,我们的目标是编写无混乱且可维护的代码。许诺是实现该目标还是vuex状态-留给各个开发人员和团队来决定。
仅提供有关一个封闭主题的信息: 您不必创建承诺,axios会自己返回一个承诺:
参考:https : //forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4
例:
export const loginForm = ({ commit }, data) => {
return axios
.post('http://localhost:8000/api/login', data)
.then((response) => {
commit('logUserIn', response.data);
})
.catch((error) => {
commit('unAuthorisedUser', { error:error.response.data });
})
}
另一个例子:
addEmployee({ commit, state }) {
return insertEmployee(state.employee)
.then(result => {
commit('setEmployee', result.data);
return result.data; // resolve
})
.catch(err => {
throw err.response.data; // reject
})
}
另一个带有async-await的示例
async getUser({ commit }) {
try {
const currentUser = await axios.get('/user/current')
commit('setUser', currentUser)
return currentUser
} catch (err) {
commit('setUser', null)
throw 'Unable to fetch current user'
}
},
动作
ADD_PRODUCT : (context,product) => {
return Axios.post(uri, product).then((response) => {
if (response.status === 'success') {
context.commit('SET_PRODUCT',response.data.data)
}
return response.data
});
});
零件
this.$store.dispatch('ADD_PRODUCT',data).then((res) => {
if (res.status === 'success') {
// write your success actions here....
} else {
// write your error actions here...
}
})
TL:DR; 仅在必要时从您的操作中返回诺言,而是将相同的操作链接在一起。
很长一段时间以来,我还认为返回动作与单向数据流的Vuex周期相矛盾。
但是,也有边缘情况,其中从你的行动返回一个承诺可能是“必要的”。
设想一种情况,可以从2个不同的组件触发一个动作,并且每个组件以不同的方式处理故障情况。在这种情况下,需要将调用者组件作为参数传递,以在存储中设置不同的标志。
哑巴的例子
用户可以在navbar和/ profile页面(其中包含navbar)中编辑用户名的页面。两者都触发一个动作“更改用户名”,这是异步的。如果承诺失败,则该页面应仅在用户试图更改用户名的组件中显示错误。
当然,这是一个愚蠢的示例,但我看不到一种方法,无需复制代码并通过2个不同的动作进行相同的调用即可解决此问题。
actions.js
const axios = require('axios');
const types = require('./types');
export const actions = {
GET_CONTENT({commit}){
axios.get(`${URL}`)
.then(doc =>{
const content = doc.data;
commit(types.SET_CONTENT , content);
setTimeout(() =>{
commit(types.IS_LOADING , false);
} , 1000);
}).catch(err =>{
console.log(err);
});
},
}
家
<script>
import {value , onCreated} from "vue-function-api";
import {useState, useStore} from "@u3u/vue-hooks";
export default {
name: 'home',
setup(){
const store = useStore();
const state = {
...useState(["content" , "isLoading"])
};
onCreated(() =>{
store.value.dispatch("GET_CONTENT" );
});
return{
...state,
}
}
};
</script>