如果一个 async Vuex action 是 运行 两次,那么 await 调用之后的代码可以是 运行 随机顺序吗?

If an async Vuex action is run twice, can the code following the await call be run in random order?

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 })
  }
}

如果上面的动作被调用两次:

store.dispatch('search', { page: 1 });
store.dispatch('search', { page: 1 });

假设第一个调用的请求需要10s完成,第二个调用的请求只需要1秒。

第二次调用await EventApi.get()之后的代码是否在第一次调用之后执行call,甚至认为请求应该早点完成?我不会这么认为,但我的实验表明情况确实如此,所以我的代码一定有问题。

这是 Vuex 日志 + 我的一些评论:

https://gist.github.com/niuage/9e2dcd509dc6d5246b3a16af56ccb3d3


如果有帮助,这里是简化的 EventApi 模块:

const get = async () => {
  const q = await fetch(someUrl);
  const result = await q.json();

  return result;
}

export default {
  get
}

我问是因为我遇到了一个问题,我的结果计数与实际显示的结果不同步,这种情况极少发生,所以我猜这可能是因为两者之间存在竞争条件多个请求。

您示例中的第二个较短的调用将首先完成。这是因为 await 仅在 async 函数的上下文中等待。

由于 async/await 是一种不同的编写承诺的方式,您可以将其视为 return 一个承诺的 2 个单独的函数调用。一个不会耽误另一个

这是一个演示:

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.

上面的演示中的 async 函数是用 .then 编写的:

function wait(id, time) {
  return delay(time).then(() => {
    console.log(id + ' complete.');
  });
}

如果您想强制示例中的第二个函数调用等待第一个函数调用,请将两个函数的调用上下文设为 async 函数,例如:

async created() {
  // Assuming the `search` action returns its http promise!
  await this.$store.dispatch('search', { page: 1 });
  await this.$store.dispatch('search', { page: 1 });
  ...
}