Svelte 3,异步 onMount 还是有效的替代方案?

Fre*_*ors 6 javascript ecmascript-6 svelte svelte-component svelte-3

我需要的是async-await在 Svelte 中使用onMount()

或者,也许您可​​以建议我什么是错误的以及我可以使用的替代方法。

再现

  1. 去这里:https : //svelte.dev/repl/000ae69c0fe14d9483678d4ace874726?version=3.23.0
  2. 打开控制台
  3. 点击按钮
  4. 你应该看到消息:"Mounting...""A lot of background work..."
  5. 如果再次单击,则不会写入销毁消息

为什么?

难道onMount()识别async功能的承诺?应该是?

我需要这种async行为,因为我需要function lazyLoading()在渲染Child组件之前等待。

在 Svelte 中是否有其他方法可以做到这一点?

Ric*_*ris 9

只是为了解释为什么onMount不能是一个async函数(这可能会在未来改变,但不要指望它):

您可以从onMount组件销毁时调用的处理程序返回一个函数。但是async函数只能返回一个 promise。由于承诺不是函数,Svelte 将忽略返回值。

useEffect顺便提一下,这与React 中的相同——该函数必须是同步的,以避免竞争条件。对于推荐的解决方案onMount是一样的useEffect-将一个async函数的处理程序:

onMount(() => {
  async function foo() {
    bar = await baz();
  }

  foo();

  return () => console.log('destroyed');
});
Run Code Online (Sandbox Code Playgroud)

(请注意,您有责任处理因组件在 promise 解决之前被销毁而产生的任何竞争条件,尽管在已销毁组件内分配状态是无害的。)

我已经打开了一个问题来讨论在这些情况下提供更有用的反馈:https : //github.com/sveltejs/svelte/issues/4944

  • @LaodeMuhammadAlFatih 不,这不是真的,据我所知。由于该文档页面长期以来一直使用 async 关键字,并且总是“错误”且令人困惑。但Rich写道:使用它是可以的,只要你不需要返回一个销毁函数。 (4认同)
  • 是的,这是完全有效的 (2认同)
  • 现在,您可以在“onMount”挂钩中使用“async”函数。请参阅 https://svelte.dev/tutorial/onmount。 (2认同)

Che*_*yDT 6

onMount必须是同步的。但是,您可以在标记和 make 中使用块例如{#await}lazyLoading async

{#await lazyLoading() then data}
  I'm the child and I loaded "{data}".
{/await}
Run Code Online (Sandbox Code Playgroud)

你也可以做...

<script>
  let dataPromise = lazyLoading()
</script>

{#await dataPromise then data}
  I'm the child and I loaded "{data}".
{/await}
Run Code Online (Sandbox Code Playgroud)

请参阅我的工作示例。

这样做的另一个好处是允许您使用加载器以及在承诺被拒绝时出现的标记,使用以下语法:

{#await promise}
  loading
{:then value}
  loaded {value}
{:catch error}
  failed with {error}
{/await}
Run Code Online (Sandbox Code Playgroud)

  • 为了清楚起见,React 具有完全相同的限制 - 你的 useEffect 处理程序(最接近的 onMount 等价物)必须同步返回清理函数,以避免竞争条件。 (2认同)