Search code examples
reactive-programmingtimingsvelte

What is the order that reactive statements are executed in?


Let's say we have the following component script

let x = 0;

function increase() {
    x += 1;
}

$: console.log(x)

$: if (x == 4) {
    x = 0;
}

https://svelte.dev/repl/2bca979673114afea9fc6b37434653a3?version=3.29.0

Intuitively I would expect from cotinually calling increase, is to have the values 0,1,2,3,4,1,2,3,4,... logged to the console. But this is not the case. Instead, the second reactive statement runs first, and 4 is never logged; it is 0. Switching the order of the reactive statements has no effect.

How do you make the logging statement execute before the other one and what is the reason that it runs second, in the first place?


Solution

  • The order in which reactive statements that depends on the same variables are run is not specified / guaranteed by Svelte. You have to build your components with the expectation that they can be run in any order, and make sure that your code doesn't depend on any specific order.

    You must not rely on a given order you observe in a specific case either -- it can change following a change in Svelte's internal implementation (e.g. new optimisations), or when the code of your own component changes (causing a different compiler output, that can change the order of reactive blocks for hard-to-anticipate reasons).

    The reasons why this happens are highly technical (i.e. I don't really know), but they boil down to ease of implementation / optimization of the compiler. Reactive statements are a kind of async operations, that typically can't guarantee order of execution.

    If you really need 2 operations to happen in a specific order then, for peace of mind, you need them in the same reactive block.

        $: {
            console.log(x)     // op 1
            if (x == 4) x = 0  // op 2
        }