Provide option to exclude or explicitly list watched properties
davidje13 opened this issue · 0 comments
I have just encountered a situation where I managed to get an infinite loop due to updating vuex state as part of an asynchronously computed property. In fairness I realise this is against the Vue principles but it is the only way I know of to display a global loading indicator.
The basic setup:
asyncComputed: {
async thing() {
console.log('beginning');
const loadId = {};
this.$store.dispatch('beginLoad', loadId);
try {
await new Promise((resolve) => setTimeout(resolve, 1000);
} finally {
this.$store.dispatch('endLoad', loadId);
}
console.log('ending');
return 1;
},
}
Store setup:
new Vuex.Store({
state: { loader: [] },
mutations: {
BEGIN_LOAD: (state, id) => { state.loader.push(id); },
END_LOAD: (state, id) => { state.loader.splice(pos, state.loader.indexOf(id)); },
},
actions: {
beginLoad({ commit }, id) { commit('BEGIN_LOAD', id); },
endLoad({ commit }, id) { commit('END_LOAD', id); },
},
}
This results in an infinite loop, where the next call is made before the first has entirely finished;
beginning beginning ending beginning ending beginning ending [...]
It appears to be caused because the change to the loading state at the end triggers a new update.
I would like to be able to explicitly remove the $store
as a watched variable, or explicitly list the properties I actually care about. I can achieve this with shouldUpdate
by storing previous variables and checking if anything I care about changed, but that makes shouldUpdate
change state which is also not good (and makes any explicit update()
calls stop working).
If this is not a use-case you want to support, I suggest at least making sure there are not two invocations in-flight at the same time; if inputs change, it should wait until the current request has finished before starting a new one