Svelte 3, async onMount or a valid alternative?

安稳与你 提交于 2020-06-14 15:33:54

问题


What I need is to use async-await in Svelte onMount().

Or maybe you can suggest me what is wrong and what I can use alternatively.

To Reproduce

  1. go here: https://svelte.dev/repl/000ae69c0fe14d9483678d4ace874726?version=3.23.0
  2. open the console
  3. click on the button
  4. you should see messages: "Mounting..." and "A lot of background work..."
  5. if you click again the destroy message is not written

WHY?

Did onMount() recognizes the async function promise? Should it?

I need that async behavior because I need to wait for function lazyLoading() before rendering the Child component.

Is there an alternative way to do this in Svelte?


回答1:


Just to explain why onMount can't be an async function (this might change in future, but don't expect it to):

You can return a function from an onMount handler that is called when the component is destroyed. But async functions can only return a promise. Since a promise isn't a function, Svelte will ignore the return value.

This is the same as useEffect in React, incidentally — the function must be synchronous in order to avoid race conditions. The recommended solution for onMount is the same as for useEffect — place an async function inside the handler:

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

  foo();

  return () => console.log('destroyed');
});

(Note that you're responsible for handling any race conditions that arise as a result of the component being destroyed before the promise resolves, though assigning state inside a destroyed component is harmless.)

I've opened an issue to discuss providing more useful feedback in these situations: https://github.com/sveltejs/svelte/issues/4944




回答2:


onMount must be synchronous. However, you can use an {#await} block in your markup and make lazyLoading async, for example:

{#await lazyLoading() then data}
  I'm the child and I loaded "{data}".
{/await}

You could also do...

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

{#await dataPromise then data}
  I'm the child and I loaded "{data}".
{/await}

See my working example here.

This has the additional benefit of allowing you to use a loader as well as markup that appears when the promise is rejected, using this syntax:

{#await promise}
  loading
{:then value}
  loaded {value}
{:catch error}
  failed with {error}
{/await}


来源:https://stackoverflow.com/questions/62087073/svelte-3-async-onmount-or-a-valid-alternative

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!