每个 Vuex 动作都会返回一个Promise。
Vuex wraps the results of the action functions into Promises。所以changeColor 中的操作:
actions: {
changeColor({ commit }, newColor) {
myAsyncCommand();
}
}
返回一个解析为undefined的Promise,并且不会等待完成myAsyncCommand();的异步代码(如果它不包含异步代码,则无需等待做)。
发生这种情况是因为上面的代码与以下代码相同:
changeColor({ commit }, newColor) {
myAsyncCommand();
return undefined;
}
当.dispatch('changeColor', ...) Vuex 将返回Promise.resolve(undefined)。
如果您希望操作返回的 Promise 等待,您应该返回一个 Promise 来让属性等待您自己。大致如下:
changeColor({ commit }, newColor) {
return new Promise((resolve, reject) => {
myAsyncCommand().then(resolve);
});
// or, simply: return myAsyncCommand();
}
下面的演示实现有更多细节:
const myStore = {
namespaced: true,
state: { color: "violet" },
mutations: {
changeColor(state, newColor) {
state.color = newColor
}
},
actions: {
changeColor_SIMPLE({ commit }, newColor) {
commit('changeColor', newColor)
},
changeColor_COMPLICATED_NO_PROMISE({ commit }, newColor) {
setTimeout(() => {
commit('changeColor', newColor)
}, 2000)
},
changeColor_COMPLICATED_WITH_PROMISE({ commit }, newColor) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('changeColor', newColor)
resolve();
}, 2000)
});
}
}
};
const store = new Vuex.Store({
modules: {
store: myStore,
}
});
new Vue({
store,
el: '#app',
methods: {
...Vuex.mapActions({
setColorSimple: 'store/changeColor_SIMPLE',
setColorComplicatedNoPromise: 'store/changeColor_COMPLICATED_NO_PROMISE',
setColorComplicatedWithPromise: 'store/changeColor_COMPLICATED_WITH_PROMISE',
}),
myMethodCallByButton(){
this.setColorSimple("blue")
.then(response => console.log("SIMPLE done"),err => console.log("SIMPLE err"));
this.setColorComplicatedNoPromise("blue")
.then(response => console.log("NO_PROMISE done"),err => console.log("NO_PROMISE err"));
this.setColorComplicatedWithPromise("blue")
.then(response => console.log("WITH_PROMISE done"),err => console.log("WITH_PROMISE err"));
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuex"></script>
<div id="app">
<p>color: {{ $store.state.store.color }}</p>
<button @click="myMethodCallByButton">click me and WAIT for 2s</button>
</div>
更新/每 cmets:
即使 mapAction/dispatch 返回一个 promise,在我的情况下,我也有义务添加一个 promise 以等待“突变”的结束。我认为,从文档中,它是通过 mapAction 精确管理的。准确吗?
如果一个动作只调用一个突变,例如:
actions: {
changeColor({ commit }, newColor) {
commit('changeColor', newColor)
return undefined; // added for clarity
}
}
那么返回的Promise 只会在commit() 完成后执行。
这不会发生,因为 Vuex 管理等待突变 (commits)。
之所以会这样,是因为无需等待。这是因为 Vuex 需要:mutations must be synchronous operations。
由于突变是同步的,上面return的行只会在前一行的代码之后执行(commit('changeColor', newColor))。
注意:如果你的 mutation 有异步代码,你应该让它们同步,因为这违背了 Vuex 的正常工作方式,并且可能产生各种意想不到的行为。