flesh out await_reactivity_loss warning

pull/15844/head
Rich Harris 3 months ago
parent c0283713e6
commit 7a08d9bee5

@ -37,15 +37,41 @@ function add() {
### await_reactivity_loss
```
Detected reactivity loss
Detected reactivity loss when reading `%name%`. This happens when state is read in an async function after an earlier `await`
```
TODO
Svelte's signal-based reactivity works by tracking which bits of state are read when a template or `$derived(...)` expression executes. If an expression contains an `await`, Svelte transforms it such that any state _after_ the `await` is also tracked — in other words, in a case like this...
```js
let total = $derived(await a + b);
```
...both `a` and `b` are tracked, even though `b` is only read once `a` has resolved, after the initial execution.
This does _not_ apply to an `await` that is not 'visible' inside the expression. In a case like this...
```js
async function sum() {
return await a + b;
}
let total = $derived(await sum());
```
...`total` will depend on `a` (which is read immediately) but not `b` (which is not). The solution is to pass the values into the function:
```js
async function sum(a, b) {
return await a + b;
}
let total = $derived(await sum(a, b));
```
### await_waterfall
```
An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app.
An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app
```
TODO

@ -32,13 +32,39 @@ function add() {
## await_reactivity_loss
> Detected reactivity loss
> Detected reactivity loss when reading `%name%`. This happens when state is read in an async function after an earlier `await`
TODO
Svelte's signal-based reactivity works by tracking which bits of state are read when a template or `$derived(...)` expression executes. If an expression contains an `await`, Svelte transforms it such that any state _after_ the `await` is also tracked — in other words, in a case like this...
```js
let total = $derived(await a + b);
```
...both `a` and `b` are tracked, even though `b` is only read once `a` has resolved, after the initial execution.
This does _not_ apply to an `await` that is not 'visible' inside the expression. In a case like this...
```js
async function sum() {
return await a + b;
}
let total = $derived(await sum());
```
...`total` will depend on `a` (which is read immediately) but not `b` (which is not). The solution is to pass the values into the function:
```js
async function sum(a, b) {
return await a + b;
}
let total = $derived(await sum(a, b));
```
## await_waterfall
> An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app.
> An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app
TODO

@ -875,7 +875,10 @@ export function get(signal) {
var was_read = from_async_derived.deps !== null && from_async_derived.deps.includes(signal);
if (!tracking && !was_read) {
w.await_reactivity_loss();
w.await_reactivity_loss(/** @type {string} */ (signal.label));
// eslint-disable-next-line no-console
console.warn(get_stack('TracedAt'));
}
}

@ -19,23 +19,24 @@ export function assignment_value_stale(property, location) {
}
/**
* Detected reactivity loss
* Detected reactivity loss when reading `%name%`. This happens when state is read in an async function after an earlier `await`
* @param {string} name
*/
export function await_reactivity_loss() {
export function await_reactivity_loss(name) {
if (DEV) {
console.warn(`%c[svelte] await_reactivity_loss\n%cDetected reactivity loss\nhttps://svelte.dev/e/await_reactivity_loss`, bold, normal);
console.warn(`%c[svelte] await_reactivity_loss\n%cDetected reactivity loss when reading \`${name}\`. This happens when state is read in an async function after an earlier \`await\`\nhttps://svelte.dev/e/await_reactivity_loss`, bold, normal);
} else {
console.warn(`https://svelte.dev/e/await_reactivity_loss`);
}
}
/**
* An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app.
* An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app
* @param {string} location
*/
export function await_waterfall(location) {
if (DEV) {
console.warn(`%c[svelte] await_waterfall\n%cAn async value (${location}) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app.\nhttps://svelte.dev/e/await_waterfall`, bold, normal);
console.warn(`%c[svelte] await_waterfall\n%cAn async value (${location}) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app\nhttps://svelte.dev/e/await_waterfall`, bold, normal);
} else {
console.warn(`https://svelte.dev/e/await_waterfall`);
}

Loading…
Cancel
Save