await
Depuis la version 5.36 de Svelte, vous pouvez le mot-clé await
dans vos composants à trois
endroits où ce n’est pas possible précédemment :
- à la racine du
<script>
de votre composant - dans des déclarations
$derived(...)
- dans votre markup
Cette fonctionnalité est actuellement expérimentale, et vous devez l’activer en ajoutant l’option
experimental.async
là où vous configurez Svelte, en général
svelte.config.js
:
export default {
compilerOptions: {
experimental: {
async: boolean;
};
}
compilerOptions: {
experimental: {
async: boolean;
}
experimental: {
async: boolean
async: true
}
}
};
Le drapeau expérimental sera supprimé avec Svelte 6.
Frontières
Actuellement, vous pouvez uniquement utiilser await
au sein d’un balise
<svelte:boundary>
ayant un snippet pending
:
<svelte:boundary>
<MyApp />
{#snippet pending()}
<p>chargement...</p>
{/snippet}
</svelte:boundary>
Cette restriction sera levée lorsque Svelte supportera le rendu côté serveur asynchrone (voir les mises en garde).
Dans le bac à sable, votre application est rendue au sein d’une frontière ayant un snippet
pending
vide, afin que vous puissez utiliserawait
sans avoir à en créer un.
Mises à jour synchronisées
Lorsqu’une expression await
dépend d’un morceau d’état particulier, les changements de cet état ne
seront pas reflétés dans l’interface avant que le travail asynchrone ne soit terminé, afin que
l’interface ne soit pas laissée dans un état inconsistant. En d’autres mots, dans un exemple comme
celui-ci...
<script>
let a = $state(1);
let b = $state(2);
async function add(a, b) {
await new Promise((f) => setTimeout(f, 500)); // délai artificiel
return a + b;
}
</script>
<input type="number" bind:value={a}>
<input type="number" bind:value={b}>
<p>{a} + {b} = {await add(a, b)}</p>
... si vous incrémentez a
, le contenu de <p>
ne sera pas immédiatement mis à jour et
n’affichera donc pas ceci —
<p>2 + 2 = 3</p>
— mais à la place, le texte affichera 2 + 2 = 4
lorsque add(a, b)
sera résolue.
Les mises à jour peuvent se superposer — une mise à jour rapide sera reflétée dans l’interface tandis qu’une mise à jour lente sera toujours en cours.
Concurrence
Svelte fera autant de travail asynchrone que possible en parallèle. Par exemple, si vous avez deux
expressions await
dans votre markup...
<p>{await one()}</p>
<p>{await two()}</p>
... les deux fonctions seront exécutées en mêmet temps, puisque ce sont des expressions indépendantes, même si elles sont visuellement séquentielles.
Ceci ne s’applique pas aux expressions await
de votre <script>
ou dans les fonctions asynchrones
— celles-ci s’exécutent comme tout autre code JavaScript asynchrone. Toutefois, il y a une
exception : les expressions $derived
indépendantes seront mises à jour indépendamment, même si
elles sont exécutées séquentiellement lors de leur création :
// ces expressions sont exécutées séquentiellement la première fois
// mais seront mises à jour indépendamment
let let a: number
a = function $derived<number>(expression: number): number
namespace $derived
Declares derived state, i.e. one that depends on other state variables.
The expression inside $derived(...)
should be free of side-effects.
Example:
let double = $derived(count * 2);
$derived(await function one(): Promise<number>
one());
let let b: number
b = function $derived<number>(expression: number): number
namespace $derived
Declares derived state, i.e. one that depends on other state variables.
The expression inside $derived(...)
should be free of side-effects.
Example:
let double = $derived(count * 2);
$derived(await function two(): Promise<number>
two());
Si vous écrivez du code comme celui-là, attendez-vous à ce que Svelte vous affiche un avertissement
await_waterfall
Indiquer les états de chargement
En plus du snippet pending
de la frontière la plus proche,
vous pouvez indiquer que du travail asynchrone est en cours avec la rune
$effect.pending()
.
Vous pouvez aussi utiliser settled()
pour obtenir une promesse qui se résout
lorsque la mise à jour actuelle se termine :
import { function tick(): Promise<void>
Returns a promise that resolves once any pending state changes have been applied.
tick, import settled
settled } from 'svelte';
async function function onclick(): Promise<void>
onclick() {
let updating: boolean
updating = true;
// sans ceci, le changement à `updating` sera groupé
// avec les autres changements, signifiant qu'il ne sera
// pas reflété dans l'interface
await function tick(): Promise<void>
Returns a promise that resolves once any pending state changes have been applied.
tick();
let color: string
color = 'octarine';
let answer: number
answer = 42;
await import settled
settled();
// toute mise à jour affectée par `color` ou `answer`
// a désormais été appliquée
let updating: boolean
updating = false;
}
Gestion des erreurs
Les erreurs dans les expressions await
vont remonter jusqu’à la frontière
d’erreur la plus proche.
Mises en garde
En tant que fonctionnalité expérimentale, les détails de comment les expressions await
sont gérées
(ainsi que les APIs liées comme $effect.pending()
) sont potentiellement sujettes à des breaking
changes en dehors d’un changement de version majeur, même si nous avons l’intention de limiter ces
changements au minimum.
Actuellement, le rendu côté serveur reste synchrone. Si une balise <svelte:boundary>
ayant un
snippet pending
est rencontrée lors du SSR, seul le snippet pending
sera affiché.
Breaking changes
Les effets sont exécutées dans un ordre légèrement différent lorsque l’option experimental.async
est à true
.
Spécifiquement, les effets de block comme {#if ...}
et {#each ...}
s’exécutent désormais avant
un $effect.pre
ou un beforeUpdate
du même composant, ce qui implique que dans de très rares
situations
il est possible de mettre à jour un bloc qui ne devrait pas exister, mais uniquement si vous mettez
à jour un état au sein d’un effet, ce que vous devriez éviter.
Modifier cette page sur Github llms.txt