Skip to content

destroy function returned from onMount is not called if onMount is passed an async function #4927

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
frederikhors opened this issue May 29, 2020 · 11 comments · Fixed by #5053

Comments

@frederikhors
Copy link

Describe the bug
What I need is to use async-await in 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 promise? Should it?

Expected behavior
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?

@leaysgur
Copy link

I don't know much about svelte internals yet, but you should do like this.

// NG
onMount(async () => {
  await xxx();
});

// OK
onMount(() => {
  (async () => {
    await xxx();
  })();
});

@antony
Copy link
Member

antony commented May 29, 2020

@frederikhors I'm pretty sure this is a bug. It seems that if you use an async function then onDestroy is not properly wired up.

I'm going to rename this issue for you and mark it as a bug.

@antony antony added the bug label May 29, 2020
@antony antony changed the title Async onMount or a valid alternative? destroy function returned from onMount is not called if onMount is passed an async function May 29, 2020
@Conduitry
Copy link
Member

This isn't really a bug, because if you have an async function that returns a function, it doesn't really return a function - it returns a promise. I don't remember whether the Svelte internals currently check for the onMount callback's return being a function or whether they check for it being truthy. Maybe there's some adjustment to be made there.

But the point is that, if onMount's callback does return a promise, how should Svelte handle that? What if the promise hasn't resolved yet by the time the component is destroyed? What do we do? If we're saying the the onMount callback needs to return a function or nothing, this is probably why.

@tanhauhau
Copy link
Member

tanhauhau commented May 29, 2020

i feel it should get a runtime warning / error, if it returns something besides function or undefined.

that's also how react is handling useEffect, which i find it reasonable

@antony
Copy link
Member

antony commented May 29, 2020

@tanhauhau I'm not sure I agree. Using an async function in onMount is a common use-case (for example, we tell people to use await import there for client-side only libraries in Sapper.

What I believe should happen is the Svelte compiler should, when a promise is passed to onMount, realise that a promise has been passed, and await the result of the function to be used as the onDestroy function.

i.e, it should behave the exact same way for an async function as it does for a non-async function (if this is possible)

@pushkine
Copy link
Contributor

pushkine commented May 29, 2020

It's not a bug, checking whether the returned value is a promise as @antony suggests really wouldn't be a big deal though, if that helps somebody ?

There's another problem however, async functions are run ( wait for it ) asynchronously, meaning that they will actually run afterFlush™.

Accepting async lifecycle functions therefore would bring confusion as to why async onMount functions ( that you specifically said were allowed and supported in the documentation ) aren't run onMount but after flush.

it all ties back to the same problem which is about general javascript knowledge.
So @tanhauhau is correct, it should throw an error.

@ghost
Copy link

ghost commented May 29, 2020

Yeah what he said... that teaches me to leave a reply open while I get lunch....

Anyways, I just see all sorts of potential for deadlock relying on a promise for onDestroy that may never resolve.

@tcd93
Copy link

tcd93 commented Feb 8, 2021

shouldn't this behavior be clarified in the tutorial too? it has async onMount as an example

@antony

@frederikhors
Copy link
Author

shouldn't this behavior be clarified in the tutorial too? it has async onMount as an example

@antony

I think we should update the tutorial, is a bad example! @antony should we reopen this?

@rnenjoy
Copy link

rnenjoy commented May 12, 2023

I'm new to svelte and i followed the tutorial and this lost me 1 day of troubleshooting.

@antony
Copy link
Member

antony commented May 12, 2023

We'd happily accept a PR to update the tutorial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants