recherche
Maisoninterface Webjs tutorielLe stockage local asynchrone est là pour vous aider

Lorsque vous entendez l'expression « Stockage local asynchrone », qu'est-ce qui vous vient à l'esprit ? Au début, vous pourriez penser qu’il s’agit d’une implémentation magique du stockage local basé sur un navigateur. Cependant, cette hypothèse est incorrecte. Le stockage local asynchrone n'est ni lié au navigateur ni un mécanisme de stockage typique. Il est probable qu'une ou deux bibliothèques que vous avez utilisées l'utilisent sous le capot. Dans de nombreux cas, cette fonctionnalité peut vous éviter de gérer un code compliqué.

Qu’est-ce que le stockage local asynchrone ?

Async Local Storage est une fonctionnalité introduite dans Node.js, initialement ajoutée dans les versions v13.10.0 et v12.17.0, puis stabilisée dans la v16.4.0. Il fait partie du module async_hooks, qui fournit un moyen de suivre les ressources asynchrones dans les applications Node.js. La fonctionnalité permet la création d'un contexte partagé auquel plusieurs fonctions asynchrones peuvent accéder sans le transmettre explicitement. Le contexte est disponible dans chaque (et unique) opération exécutée dans le rappel transmis à la méthode run() de l'instance AsyncLocalStorage.

Un modèle pour utiliser AsyncLocalStorage

Avant de plonger dans les exemples, expliquons le modèle que nous allons utiliser.

Initialisation

import { AsyncLocalStorage } from "async_hooks";
import { Context } from "./types";

export const asyncLocalStorage = new AsyncLocalStorage<context>();

// export const authAsyncLocalStorage = new AuthAsyncLocalStorage<authcontext>()
</authcontext></context>

Dans le module ci-dessus, nous initialisons une instance de AsyncLocalStorage et l'exportons sous forme de variable.

Utilisation

asyncLocalStorage.run({ userId }, async () => {
  const usersData: UserData = await collectUsersData();
  console.log("usersData", usersData);
});

// (method) AsyncLocalStorage<unknown>.run<promise>>(store: unknown, callback: () => Promise<void>): Promise<void> (+1 overload)
</void></void></promise></unknown>

La méthode run() prend deux arguments : storage, qui contient les données que nous souhaitons partager, et callback, où nous plaçons notre logique. En conséquence, le stockage devient accessible à chaque appel de fonction dans le rappel, permettant un partage transparent des données entre les opérations asynchrones.

async function collectUsersData() {
  const context = asyncLocalStorage.getStore();
}

Pour accéder au contexte, nous importons notre instance et appelons la méthode asyncLocalStorage.getStore(). Ce qui est bien, c'est que le stockage récupéré depuis getStore() est typé car nous avons transmis le type Context à AsyncLocalStorage lors de l'initialisation : new AsyncLocalStorage().

Stockage local asynchrone comme contexte d'authentification

Il n'y a pas d'application web sans système d'authentification. Nous devons valider les jetons d'authentification et extraire les informations utilisateur. Une fois que nous avons obtenu l'identité de l'utilisateur, nous souhaitons la rendre disponible dans les gestionnaires de routes et éviter de dupliquer le code dans chacun d'eux. Voyons comment nous pouvons utiliser AsyncLocalStorage pour implémenter un contexte d'authentification tout en gardant notre code propre.

J'ai choisi fastify pour cet exemple.

Selon la documentation, fastify est :

Framework Web rapide et faible, pour Node.js

Ok, commençons :

  1. Installer fastify :
import { AsyncLocalStorage } from "async_hooks";
import { Context } from "./types";

export const asyncLocalStorage = new AsyncLocalStorage<context>();

// export const authAsyncLocalStorage = new AuthAsyncLocalStorage<authcontext>()
</authcontext></context>
  1. Définir le type pour notre contexte d'authentification :
asyncLocalStorage.run({ userId }, async () => {
  const usersData: UserData = await collectUsersData();
  console.log("usersData", usersData);
});

// (method) AsyncLocalStorage<unknown>.run<promise>>(store: unknown, callback: () => Promise<void>): Promise<void> (+1 overload)
</void></void></promise></unknown>
  1. Initialisez une instance de AsyncLocalStorage, attribuez-la à une variable et exportez la variable. N'oubliez pas de transmettre le type approprié : new AsyncLocalStorage().
async function collectUsersData() {
  const context = asyncLocalStorage.getStore();
}
  1. Initialisez une instance Fastify et ajoutez un utilitaire de gestion des erreurs :
npm install fastify

Vient maintenant la partie très importante. Nous allons ajouter un hook onRequest pour envelopper les gestionnaires avec la méthode authAsyncLocalStorage.run().

type Context = Map;

Après une validation réussie, nous appelons la méthode run() depuis notre authAsyncLocalStorage. Comme argument de stockage, nous transmettons le contexte d'authentification avec l'ID utilisateur récupéré du jeton. Dans le rappel, nous appelons la fonction done pour continuer le cycle de vie Fastify.

Si nous avons des contrôles d'authentification qui nécessitent des opérations asynchrones, nous devons les ajouter au rappel. En effet, selon la documentation :

le rappel terminé n'est pas disponible lors de l'utilisation de async/await ou du renvoi d'une promesse. Si vous invoquez un rappel effectué dans cette situation, un comportement inattendu peut se produire, par ex. appel en double des gestionnaires

Voici un exemple de ce à quoi cela pourrait ressembler :

import { AsyncLocalStorage } from "async_hooks";
import { Context } from "./types";

export const authAsyncLocalStorage = new AsyncLocalStorage<context>();
</context>

Notre exemple ne comporte qu'un seul itinéraire protégé. Dans des scénarios plus complexes, vous devrez peut-être encapsuler uniquement des routes spécifiques avec le contexte d'authentification. Dans de tels cas, vous pouvez soit :

  1. Enveloppez le hook onRequest dans un plugin personnalisé qui s'applique uniquement à des routes spécifiques.
  2. Ajoutez une logique de distinction de route dans le hook onRequest lui-même.

Très bien, notre contexte est posé et nous pouvons désormais définir un itinéraire protégé :

import Fastify from "fastify";

/* other code... */

const app = Fastify();

function sendUnauthorized(reply: FastifyReply, message: string) {
  reply.code(401).send({ error: `Unauthorized: ${message}` });
}

/* other code... */

Le code est assez simple. Nous importons authAsyncLocalStorage, récupérons l'userId, initialisons UserRepository et récupérons les données. Cette approche permet au gestionnaire d'itinéraire de rester propre et concentré.

Explorer comment Next.js utilise le stockage local asynchrone

Dans cet exemple, nous allons réimplémenter l'assistant de cookies de Next.js. Mais attendez, c'est un article sur AsyncLocalStorage, n'est-ce pas ? Alors pourquoi parle-t-on de cookies ? La réponse est simple : Next.js utilise AsyncLocalStorage pour gérer les cookies sur le serveur. C'est pourquoi lire un cookie dans un composant serveur est aussi simple que :

import Fastify from "fastify";
import { authAsyncLocalStorage } from "./context";
import { getUserIdFromToken, validateToken } from "./utils";

/* other code... */

app.addHook(
  "onRequest",
  (request: FastifyRequest, reply: FastifyReply, done: () => void) => {
    const accessToken = request.headers.authorization?.split(" ")[1];
    const isTokenValid = validateToken(accessToken);
    if (!isTokenValid) {
      sendUnauthorized(reply, "Access token is invalid");
    }
    const userId = accessToken ? getUserIdFromToken(accessToken) : null;

    if (!userId) {
      sendUnauthorized(reply, "Invalid or expired token");
    }
    authAsyncLocalStorage.run(new Map([["userId", userId]]), async () => {
      await new Promise((resolve) => setTimeout(resolve, 2000));
      sendUnauthorized(reply, "Invalid or expired token");
      done();
    });
  },
);

/* other code... */

Nous utilisons la fonction cookies exportée depuis next/headers, qui propose plusieurs méthodes de gestion des cookies. Mais comment est-ce techniquement possible ?

Il est maintenant temps de commencer notre réimplémentation"

Tout d'abord, je tiens à mentionner que cet exemple est basé sur les connaissances que j'ai acquises grâce à une superbe vidéo, de Lee Robinson et en plongeant dans le référentiel Next.js.

Dans cet exemple, nous utiliserons Hono comme framework de serveur. Je l'ai choisi pour deux raisons :

  1. Je voulais juste essayer.
  2. Il offre un support solide pour JSX.

Première installation de Hono :

import { AsyncLocalStorage } from "async_hooks";
import { Context } from "./types";

export const asyncLocalStorage = new AsyncLocalStorage<context>();

// export const authAsyncLocalStorage = new AuthAsyncLocalStorage<authcontext>()
</authcontext></context>

Maintenant, initialisez Hono et ajoutez un middleware :

asyncLocalStorage.run({ userId }, async () => {
  const usersData: UserData = await collectUsersData();
  console.log("usersData", usersData);
});

// (method) AsyncLocalStorage<unknown>.run<promise>>(store: unknown, callback: () => Promise<void>): Promise<void> (+1 overload)
</void></void></promise></unknown>

Le code ressemble au middleware de l'exemple Fastify, n'est-ce pas ? Pour définir le contexte, nous utilisons setCookieContext, qui est importé du module cookies - notre implémentation simple et personnalisée de la fonction cookies. Suivons la fonction setCookieContext et naviguons jusqu'au module à partir duquel elle a été importée :

async function collectUsersData() {
  const context = asyncLocalStorage.getStore();
}

La fonction setCookieContext (dont nous avons transmis la valeur de retour à cookieAsyncLocalStorage.run() dans le middleware Hono) extrait les cookies du paramètre c, qui représente le contexte hono, et les regroupe avec des fermetures qui fournissent des fonctions utilitaires pour gérer les cookies.

Notre fonction cookies reproduit la fonctionnalité des cookies de next/headers. Il utilise la méthode cookieAsyncLocalStorage.getStore() pour accéder au même contexte qui est transmis à cookieAsyncLocalStorage.run() lorsqu'il est appelé.

Nous avons enveloppé le retour de notre fonction cookies dans une promesse d'imiter le comportement de l'implémentation Next.js. Avant la version 15, cette fonction était synchrone. Désormais, dans le code Next.js actuel, les méthodes renvoyées par les cookies sont attachées à un objet de promesse, comme le montre l'exemple simplifié suivant :

npm install fastify

Un autre point à mentionner est que dans notre cas, l'utilisation de cookies.setCookie et cookies.deleteCookie génère toujours une erreur, similaire au comportement observé dans Next.js lors de la définition de cookies dans un composant serveur. Nous avons codé en dur cette logique car, dans l'implémentation d'origine, la possibilité d'utiliser setCookie ou deleteCookie dépend de la propriété phase(WorkUnitPhase) stockée dans le stockage appelé RequestStore (il s'agit de l'implémentation d'AsyncLocalStorage et stocke également les cookies). Cependant, ce sujet conviendrait mieux à un autre article. Pour garder cet exemple simple, omettons la simulation de WorkUnitPhase.

Nous devons maintenant ajouter notre code React.

  1. Ajoutez le composant App :
type Context = Map;
  1. Ajouter un composant de gestion des cookies :
import { AsyncLocalStorage } from "async_hooks";
import { Context } from "./types";

export const authAsyncLocalStorage = new AsyncLocalStorage<context>();
</context>

L'utilisation des cookies est similaire à celle utilisée dans les composants du serveur Next.js React.

  1. Ajoutez un gestionnaire de route pour afficher le modèle :
import Fastify from "fastify";

/* other code... */

const app = Fastify();

function sendUnauthorized(reply: FastifyReply, message: string) {
  reply.code(401).send({ error: `Unauthorized: ${message}` });
}

/* other code... */

Notre modèle est rendu par la méthode html à partir du contexte hono. Le point clé ici est que le gestionnaire de route s'exécute dans la méthode asyncLocalStorage.run(), qui prend cookieContext. De ce fait, nous pouvons accéder à ce contexte dans le composant DisplayCookies via la fonction cookies.

Il n'est pas possible de définir des cookies dans les composants du serveur React, nous devons donc le faire manuellement :

Async Local Storage is Here to Help You

Actualisons une page :

Async Local Storage is Here to Help You

Et voilà, nos cookies sont récupérés et affichés avec succès.

Conclusions

Il existe de nombreux autres cas d'utilisation pour asyncLocalStorage. Cette fonctionnalité vous permet de créer des contextes personnalisés dans presque n'importe quelle infrastructure de serveur. Le contexte asyncLocalStorage est encapsulé dans l'exécution de la méthode run(), ce qui facilite sa gestion. Il est parfait pour gérer des scénarios basés sur des requêtes. L'API est simple et flexible, permettant l'évolutivité en créant des instances pour chaque état. Il est possible de gérer de manière transparente des contextes séparés pour des éléments tels que l'authentification, la journalisation et les indicateurs de fonctionnalités.

Malgré ses avantages, il y a quelques considérations à garder à l’esprit. J'ai entendu des opinions selon lesquelles asyncLocalStorage introduit trop de « magie » dans le code. J'avoue que lorsque j'ai utilisé cette fonctionnalité pour la première fois, il m'a fallu un certain temps pour bien comprendre le concept. Une autre chose à considérer est que l’importation du contexte dans un module crée une nouvelle dépendance que vous devrez gérer. Cependant, en fin de compte, transmettre des valeurs via des appels de fonctions profondément imbriqués est bien pire.

Merci d'avoir lu et à bientôt dans le prochain post !?

PS : Vous pouvez retrouver les exemples (plus un bonus) ici

Source du message Bog : https://www.aboutjs.dev/en/async-local-storage-is-here-to-help-you

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisationPython vs JavaScript: la courbe d'apprentissage et la facilité d'utilisationApr 16, 2025 am 12:12 AM

Python convient plus aux débutants, avec une courbe d'apprentissage en douceur et une syntaxe concise; JavaScript convient au développement frontal, avec une courbe d'apprentissage abrupte et une syntaxe flexible. 1. La syntaxe Python est intuitive et adaptée à la science des données et au développement back-end. 2. JavaScript est flexible et largement utilisé dans la programmation frontale et côté serveur.

Python vs JavaScript: communauté, bibliothèques et ressourcesPython vs JavaScript: communauté, bibliothèques et ressourcesApr 15, 2025 am 12:16 AM

Python et JavaScript ont leurs propres avantages et inconvénients en termes de communauté, de bibliothèques et de ressources. 1) La communauté Python est amicale et adaptée aux débutants, mais les ressources de développement frontal ne sont pas aussi riches que JavaScript. 2) Python est puissant dans les bibliothèques de science des données et d'apprentissage automatique, tandis que JavaScript est meilleur dans les bibliothèques et les cadres de développement frontaux. 3) Les deux ont des ressources d'apprentissage riches, mais Python convient pour commencer par des documents officiels, tandis que JavaScript est meilleur avec MDNWEBDOCS. Le choix doit être basé sur les besoins du projet et les intérêts personnels.

De C / C à JavaScript: comment tout cela fonctionneDe C / C à JavaScript: comment tout cela fonctionneApr 14, 2025 am 12:05 AM

Le passage de C / C à JavaScript nécessite de s'adapter à la frappe dynamique, à la collecte des ordures et à la programmation asynchrone. 1) C / C est un langage dactylographié statiquement qui nécessite une gestion manuelle de la mémoire, tandis que JavaScript est dynamiquement typé et que la collecte des déchets est automatiquement traitée. 2) C / C doit être compilé en code machine, tandis que JavaScript est une langue interprétée. 3) JavaScript introduit des concepts tels que les fermetures, les chaînes de prototypes et la promesse, ce qui améliore la flexibilité et les capacités de programmation asynchrones.

Moteurs JavaScript: comparaison des implémentationsMoteurs JavaScript: comparaison des implémentationsApr 13, 2025 am 12:05 AM

Différents moteurs JavaScript ont des effets différents lors de l'analyse et de l'exécution du code JavaScript, car les principes d'implémentation et les stratégies d'optimisation de chaque moteur diffèrent. 1. Analyse lexicale: convertir le code source en unité lexicale. 2. Analyse de la grammaire: générer un arbre de syntaxe abstrait. 3. Optimisation et compilation: générer du code machine via le compilateur JIT. 4. Exécuter: Exécutez le code machine. Le moteur V8 optimise grâce à une compilation instantanée et à une classe cachée, SpiderMonkey utilise un système d'inférence de type, résultant en différentes performances de performances sur le même code.

Au-delà du navigateur: Javascript dans le monde réelAu-delà du navigateur: Javascript dans le monde réelApr 12, 2025 am 12:06 AM

Les applications de JavaScript dans le monde réel incluent la programmation côté serveur, le développement des applications mobiles et le contrôle de l'Internet des objets: 1. La programmation côté serveur est réalisée via Node.js, adaptée au traitement de demande élevé simultané. 2. Le développement d'applications mobiles est effectué par le reactnatif et prend en charge le déploiement multiplateforme. 3. Utilisé pour le contrôle des périphériques IoT via la bibliothèque Johnny-Five, adapté à l'interaction matérielle.

Construire une application SaaS multi-locataire avec next.js (intégration backend)Construire une application SaaS multi-locataire avec next.js (intégration backend)Apr 11, 2025 am 08:23 AM

J'ai construit une application SAAS multi-locataire fonctionnelle (une application EdTech) avec votre outil technologique quotidien et vous pouvez faire de même. Premièrement, qu'est-ce qu'une application SaaS multi-locataire? Les applications saas multi-locataires vous permettent de servir plusieurs clients à partir d'un chant

Comment construire une application SaaS multi-locataire avec Next.js (Frontend Integration)Comment construire une application SaaS multi-locataire avec Next.js (Frontend Integration)Apr 11, 2025 am 08:22 AM

Cet article démontre l'intégration frontale avec un backend sécurisé par permis, construisant une application fonctionnelle EdTech SaaS en utilisant Next.js. Le frontend récupère les autorisations des utilisateurs pour contrôler la visibilité de l'interface utilisateur et garantit que les demandes d'API adhèrent à la base de rôles

JavaScript: Explorer la polyvalence d'un langage WebJavaScript: Explorer la polyvalence d'un langage WebApr 11, 2025 am 12:01 AM

JavaScript est le langage central du développement Web moderne et est largement utilisé pour sa diversité et sa flexibilité. 1) Développement frontal: construire des pages Web dynamiques et des applications à une seule page via les opérations DOM et les cadres modernes (tels que React, Vue.js, Angular). 2) Développement côté serveur: Node.js utilise un modèle d'E / S non bloquant pour gérer une concurrence élevée et des applications en temps réel. 3) Développement des applications mobiles et de bureau: le développement de la plate-forme multiplateuse est réalisé par réact noral et électron pour améliorer l'efficacité du développement.

See all articles

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semainesBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semainesBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌

Outils chauds

MantisBT

MantisBT

Mantis est un outil Web de suivi des défauts facile à déployer, conçu pour faciliter le suivi des défauts des produits. Cela nécessite PHP, MySQL et un serveur Web. Découvrez nos services de démonstration et d'hébergement.

Adaptateur de serveur SAP NetWeaver pour Eclipse

Adaptateur de serveur SAP NetWeaver pour Eclipse

Intégrez Eclipse au serveur d'applications SAP NetWeaver.

VSCode Windows 64 bits Télécharger

VSCode Windows 64 bits Télécharger

Un éditeur IDE gratuit et puissant lancé par Microsoft

SublimeText3 version anglaise

SublimeText3 version anglaise

Recommandé : version Win, prend en charge les invites de code !

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Puissant environnement de développement intégré PHP