const actions = {
search: debounce(
async ({ commit, dispatch, getters, rootGetters }, { page = 1 }) => {
commit("setLoading", true);
commit("setPage", page);
console.log("Starting...")
const randId = Math.random() * 100;
console.log(randId);
const results = await EventApi.get();
console.log("Done: ", randId, `|${results.meta.slept}|`)
// After `await`
commit(page == 1 ? "setEvents" : "addEvents", results.events);
// ... and a bunch more commits after that.
}, 300, { leading: true, trailing: true })
}
}
If the action above is called twice:
store.dispatch('search', { page: 1 });
store.dispatch('search', { page: 1 });
Let's assume the request made by the first call takes 10s to complete, and the request made by the second one takes only 1 second.
Is the code after await EventApi.get()
in the second call executed after the one in the first call, even thought the request should have finished way earlier? I wouldn't have thought so but my experiment showed that it was the case, so something must be wrong with my code.
Here are the Vuex logs + some of my comments:
https://gist.github.com/niuage/9e2dcd509dc6d5246b3a16af56ccb3d3
In case it helps, here's the simplified EventApi module:
const get = async () => {
const q = await fetch(someUrl);
const result = await q.json();
return result;
}
export default {
get
}
I'm asking because I'm having an issue where, super rarely, I get my result count out of sync with the results actually displayed, so I was guessing that it could be because there was a race condition between multiple requests.
The second, shorter, call in your example would complete first. This is because the await
only waits within the context of the async
function.
Since async/await
is a different way of writing promises, you can think of it as 2 separate function calls that return a promise. The one would not delay the other.
Here's a demo:
const delay = time => new Promise(resolve => setTimeout(() => resolve(), time))
async function wait(id, time) {
await delay(time);
console.log(id + ' complete.');
}
console.log('Starting 1...');
wait('#1', 5000);
console.log('Starting 2...');
wait('#2', 1000);
View the bottom portion of the demo for the console results.
Here's the async
function from the demo above written with .then
instead:
function wait(id, time) {
return delay(time).then(() => {
console.log(id + ' complete.');
});
}
If you wanted to force the second function call in your example to wait for the first, make the calling context of both an async
function, for example:
async created() {
// Assuming the `search` action returns its http promise!
await this.$store.dispatch('search', { page: 1 });
await this.$store.dispatch('search', { page: 1 });
...
}