【问题标题】:vue async call in created() lifecycle hookcreated() 生命周期钩子中的 vue 异步调用
【发布时间】:2020-04-06 05:05:03
【问题描述】:

我需要在created() 中调用下面的方法。为此,我需要将created() 设为async。根据 Vue 文档,created()同步调用。 Vue Framework await 会在 created() 上避免任何竞争条件吗?

this.isAuthenticated = await authService.isAuthenticated();

【问题讨论】:

  • 作为评论发布,因为它是轶事:我在使用 async 和 created 方面取得了不同程度的成功。例如,当mounted 中的某些内容依赖于created 中异步调用的解析时,使created 异步并不能修复竞争条件,因为mounted 将在created 完成之前开始执行。也就是说,将async 附加到created() 不会抛出错误,您当然可以在其中使用await
  • GitHub 上关于它的讨论非常长(异步生命周期挂钩)。它提供了很多关于它为什么有用的很好的讨论,以及为什么它还没有完成(在讨论中):github.com/vuejs/vue/issues/7209 ...如果你想阅读更多关于它的信息。
  • @MattU 在发布我的解决方案之前,我在 Github 上搜索了这个帖子,找到了 Vue 的作者的声明,其中他说生命挂钩将是异步的。我找不到它。你会联想到这样的说法吗?
  • 这也是 Angular 和 React 中的反模式以及 Vue 中的 AFAIK。解决方案是将 Promise 移到组件之外,在 Promise 完成之前不要实例化它。

标签: vue.js vuejs2


【解决方案1】:

Vue.config.productionTip = false;

function tm(ms, msg) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(msg);
    }, ms);
  });
}

new Vue({
  async beforeCreate() {
    console.log(await tm(1000, "BEFORE CREATE"));
  },
  async created() {
    console.log(await tm(2000, "CREATED"));
  },
  async beforeMount() {
    console.log(await tm(3000, "BEFORE MOUNT"));
  },
  async mounted() {
    console.log(await tm(4000, "MOUNTED"));
  }
}).$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

【讨论】:

  • 我不太确定这是否能解决问题。你为什么要等那么久?如果created 中的awaited 调用耗时超过4s 怎么办?然后mounted 仍将在awaited 代码返回之前被调用。还是不正确?
  • @MattU 实际上,这不是问题的严格答案。我只是想证明生命钩子是异步工作的。显然,这样的答案适合作者。
  • 很公平。显然是的,是的。 :)
  • 我不认为这实际上是异步的。 tm 调用几乎同时发生,但输出间隔 1 秒。因此,它只显示为异步的。
  • 是的,你可以这样做,问题是:那些没有被等待。所以它有点误导的答案。我也看到人们用 webcomponents 来做这件事。拥有异步功能并等待其完成并不是一回事。事实上,你可以在任何地方放置一个异步函数,它只是有时会产生意想不到的结果,即调用者没有预料到,因此没有等待。
【解决方案2】:

如果你真的需要等到你的异步函数完成。您基本上可以在创建 Vue 实例之前等待它。这可能并不总是可用的,但在类似这个问题的情况下它是可用的,而且它比放置一个不等待的异步生命周期钩子更可靠。

Vue.config.productionTip = false;

// mock service
const authService = {
  isAuthenticated: () => new Promise((r) => setTimeout(() => r(true), 2000))
};


// async iife to await the promise before creating the instance
(async() => {
  const isAuthenticated = await authService.isAuthenticated();
  new Vue({
    data: {
      isAuthenticated
    },
    created() {
      console.log('authenticaed:', this.isAuthenticated);
    },
  })
})().catch(console.warn);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

【讨论】:

    猜你喜欢
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    • 2018-04-23
    • 2018-09-09
    • 2021-03-26
    • 2021-01-09
    相关资源
    最近更新 更多