DEV Community

Cover image for Svelte Script Code Execution Order
Ido Schacham
Ido Schacham

Posted on

Svelte Script Code Execution Order

While working on my first Svelte project for a Wunderdog customer, I was caught by surprise—not by Svelte being very effective and fun to work with, that part I already knew.

What surprised me was the order in which Svelte was executing JavaScript code, especially when mixing up asynchronous functions, reactive statements, and onMount.

For example, take a look at this Svelte component, or head to the Svelte REPL. In which order will these console logs appear? Go ahead and write it down before you continue reading.

<script>
  import { onMount } from 'svelte'

  const fetchData = async () => {
    console.log('1. fetchData')
  }

  console.log('2. started')

  fetchData().then(() => console.log('3. fetched'))

  $: console.log('4. reactive')

  console.log('5. continued')

  onMount(() => {
    console.log('6. onMount')
  })

  console.log('7. after mount')
</script>
Enter fullscreen mode Exit fullscreen mode

The Answer

2. started
1. fetchData
5. continued
7. after mount
4. reactive
6. onMount
3. fetched

Why is that? Let’s investigate

2. started

The fetchData constant is assigned to an asynchronous function. The function isn’t called yet, so it doesn’t log anything at the moment. Hence, the first log that appears in the console is 2. started.

1. fetchData

Next, the fetchData function is called, thus 1. fetchData is logged to the console. The callback .then(() => console.log('3. fetched')) isn’t called just yet—it’s added to the browser’s message queue, and will be called once the event loop reaches it, a bit later.

5. continued

Shouldn’t 4. reactive be logged now? That’s what I thought, but turns out I was wrong. According to the Svelte docs:

Reactive statements run after other script code and before the component markup is rendered, whenever the values that they depend on have changed.

Indeed, other script code hasn’t finished running yet. Therefore, this reactive statement isn’t executed at this time, and the next console log is 5. continued.

7. after mount

7. after mount is logged to the console. That’s because the callback in onMount will only be called once the component is first rendered, and that hasn’t happened yet.

4. reactive

Now we hit that sweet spot after other script code has been executed, and before the component markup is rendered. This means it’s time to execute that reactive statement, thus logging 4. reactive to the console.

6. onMount

At this point there is no more script code to execute and the component is rendered. Thus, the onMount callback is called and 6. onMount is logged to the console.

3. fetched

What about the callback to our asynchronous function, remember that? Oh yeah, says the event loop, as it handles the message queue. The callback is executed, and finally, 3. fetched is logged to the console.

Done

While I find Svelte to be very intuitive and developer friendly, the script execution order can be a bit puzzling when using asynchronous functions and reactive statements. I hope that this post has helped you to understand this issue and to squash your bugs.

Photo by Cookie the Pom on Unsplash

Top comments (1)

Collapse
 
myleftshoe profile image
myleftshoe

thank for stepping through this, it confirms that my habit of putting all reactive statements at the end of the script block is meaningful