Maison > interface Web > js tutoriel > Opérations asynchrones dans React Redux Applications

Opérations asynchrones dans React Redux Applications

Lisa Kudrow
Libérer: 2025-02-16 12:02:12
original
496 Les gens l'ont consulté

Async Operations in React Redux Applications

Points clés

  • La nature unique du JavaScript signifie que les opérations asynchrones, telles que les appels d'API, sont essentielles à des UIS non bloquantes, et la manipulation efficace de ces opérations est essentielle dans les applications React Redux.
  • Redux Thunk, Redux-Saga et Redux-Observables sont du middleware de gestion de l'opération asynchrone Redux populaire, chacun offrant des avantages différents basés sur la complexité et les besoins de l'application.
  • redux thunk simplifie la distribution d'action asynchrone en permettant aux fonctions de retour au lieu de l'action, permettant des appels d'API séquentiels et du traitement des données liées dans ces fonctions.
  • redux-saga exploite les générateurs ES6 pour fournir des solutions plus puissantes pour des scénarios complexes tels que la gestion des conditions de course, des pauses et des opérations d'annuler, ce qui le rend adapté à de grandes applications.
  • Redux-Observables exploite les RXJ pour fournir un moyen puissant de gérer les effets secondaires à travers les flux d'action, offrant une excellente évolutivité et contrôle sur les opérations asynchrones dans des architectures d'application complexes.

Cet article a été initialement publié dans CodeBrahma.

JavaScript est un langage de programmation unique. C'est-à-dire que lorsque vous écrivez le code suivant ...

Async Operations in React Redux Applications

… La deuxième ligne ne sera exécutée qu'après l'exécution de la première ligne. Ce ne sera pas un problème dans la plupart des cas, car le client ou le serveur effectue des millions de calculs par seconde. Nous ne remarquons ces effets que lorsque nous effectuons des calculs coûteux (une tâche qui prend un certain temps à compléter - une demande de réseau prend un certain temps à revenir).

Pourquoi est-ce que je montre uniquement des appels API (demandes de réseau) ici? Qu'en est-il des autres opérations asynchrones? Les appels API sont un exemple très simple et utile pour décrire comment gérer les opérations asynchrones. Il existe d'autres opérations, telles que setTimeout(), l'informatique à forte intensité de performances, le chargement d'image et toutes les opérations axées sur les événements.

Lors de la création d'une application, nous devons considérer comment l'exécution asynchrone affecte la structure. Par exemple, pensez à fetch() comme une fonction qui effectue un appel API (demande de réseau) du navigateur. (Ignorez s'il s'agit d'une demande Ajax. Traitez simplement son comportement comme asynchrone ou synchrone.) Le temps écoulé lorsque la demande est traitée sur le serveur ne se produit pas sur le thread principal. Par conséquent, votre code JS continuera d'exécuter et une fois que la demande renvoie une réponse, elle mettra à jour le thread.

Considérez ce code:

userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans ce cas, puisque fetch() est asynchrone, lorsque nous essayons d'obtenir userDetails, nous n'aurons pas userId. Nous devons donc le construire d'une manière qui garantit que la deuxième ligne n'est exécutée qu'après que la première ligne renvoie la réponse.

La plupart des implémentations de demande de réseau modernes sont asynchrones. Mais cela ne fonctionne pas toujours parce que nous comptons sur les données de réponse API précédentes pour les appels API ultérieurs. Voyons comment le construire spécifiquement dans une application ReactJS / Redux.

React est une bibliothèque frontale pour créer des interfaces utilisateur. Redux est un conteneur d'état qui gère l'intégralité de l'état d'une application. L'utilisation de React with Redux nous permet de créer des applications efficaces et évolutives. Dans une telle application React, il existe plusieurs façons de construire des opérations asynchrones. Pour chaque méthode, nous discuterons de ses avantages et inconvénients en termes des facteurs suivants:

  • CODE CLARITY
  • Évolutivité
  • Facile à gérer les erreurs

Pour chaque méthode, nous exécuterons ces deux appels API:

1. userDetails Supposons que le point final soit . Il comprendra la ville dans la réponse. La réponse sera un objet:

2. /details Supposons que le point final soit

. La réponse sera un tableau:
userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

N'oubliez pas que nous ne pouvons faire la deuxième demande qu'après la fin de la première demande (car cela dépend de la première demande). Jetons un coup d'œil à diverses méthodes: Utilisez la promesse ou async / attend directement avec

/restuarants/:city en utilisant redux thunk

userDetails: {
  …
  city: 'city',
  …
};
Copier après la connexion
Copier après la connexion
en utilisant redux-saga

en utilisant des observables redux
  • setState J'ai spécifiquement choisi les méthodes ci-dessus car ce sont les méthodes les plus couramment utilisées dans les grands projets. Il existe encore d'autres méthodes qui peuvent être plus spécifiques à une tâche spécifique et n'ont pas toutes les fonctionnalités requises par une application complexe (par exemple
  • redux-async, redux-promis, redux-async-fiue
  • ).
  • promet
  • Promise est un objet qui peut produire une seule valeur à un moment donné dans le futur: une valeur analysée ou une cause non résolue (par exemple, une erreur de réseau s'est produite). - Eric Elliot

Dans notre exemple, nous utiliserons la bibliothèque Axios pour obtenir les données, ce qui renvoie une promesse lorsque nous ferons une demande de réseau. La promesse peut analyser et renvoyer une réponse ou lancer une erreur. Ainsi, une fois que le composant réact

est monté, nous pouvons l'obtenir directement comme ceci:

De cette manière, lorsque l'État change (en raison de l'acquisition), le composant

sera automatiquement renforcer et charger la liste des restaurants.

Async / Await est une nouvelle implémentation que nous pouvons utiliser pour effectuer des opérations asynchrones. Par exemple, la même fonction peut être obtenue par:

Les deux méthodes sont les plus faciles. Étant donné que toute la logique est à l'intérieur du composant, nous pouvons facilement obtenir toutes les données à la fois après le chargement du composant.
['restaurant1', 'restaurant2', …]
Copier après la connexion

Inconvénients de cette méthode Le problème se pose lorsque des interactions complexes basées sur des données se produisent. Par exemple, considérez la situation suivante:

Async Operations in React Redux Applications

  • Nous ne voulons pas que l'exécution de threads soit bloquée par les demandes de réseau.
  • Toutes les situations ci-dessus rendent le code très complexe et difficile à maintenir et à tester.
  • De plus, l'évolutivité sera un gros problème car si nous prévoyons de modifier le flux de l'application, nous devons supprimer toutes les opérations de récupération du composant.
  • Imaginez ce que nous ferions si le composant était au-dessus de l'arbre parent-enfant. Ensuite, nous devons modifier tous les composants de représentation qui dépendent des données.
  • Notez également que la logique métier entière se trouve dans le composant.

Comment améliorer-nous?

  1. La gestion du statut utilisant le stockage global peut réellement résoudre la moitié de nos problèmes dans ces cas. Nous utiliserons Redux comme stockage global.

  2. Déplacez la logique métier au bon endroit si nous envisageons de déplacer la logique métier hors du composant, où pouvons-nous exactement le faire? Dans les actions? Dans les réducteurs? Via middleware? L'architecture de Redux est synchrone. Une fois que vous avez distribué une action (objet JS) et qu'il atteint le stockage, le réducteur fonctionnera dessus.

  3. Assurez-vous qu'il existe un thread séparé qui exécute le code asynchrone et que toute modification de l'état global peut être récupérée par abonnement

Async Operations in React Redux Applications

À partir de cela, nous pouvons apprendre que si nous déplaçons toute la logique d'acquisition avant le réducteur - c'est-à-dire l'action ou le middleware - alors nous pouvons distribuer l'action correcte au bon moment. Par exemple, une fois que la récupération commence, nous pouvons distribuer dispatch({ type: 'FETCH_STARTED' }), et lorsqu'elle est terminée, nous pouvons distribuer dispatch({ type: 'FETCH_SUCCESS' }).

Vous souhaitez développer une application React JS?

en utilisant redux thunk

redux Thunk est un middleware pour redux. Il nous permet essentiellement de renvoyer des fonctions au lieu d'objets comme action. Cela aide à fournir dispatch et getState comme paramètres de la fonction. Nous utilisons dispatch pour distribuer les actions nécessaires au bon moment. Les avantages sont:

  • Autoriser plusieurs distributions dans la fonction
  • L'Association de la logique commerciale avec l'acquisition sera déplacée de la composante React aux actions.

Dans notre exemple, nous pouvons réécrire l'action comme ceci:

userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme vous pouvez le voir, nous avons maintenant un bon contrôle sur le type d'action distribué. Chaque appel de fonction (comme fetchStarted(), fetchUserDetailsSuccess(), fetchRestaurantsSuccess() et fetchError()) distribuera une action de l'objet JavaScript normal de type, et des détails supplémentaires peuvent être ajoutés si nécessaire. Alors maintenant, la tâche de réducteur est de traiter chaque action et de mettre à jour la vue. Je n'ai pas discuté de réducteur car c'est simple d'ici et la mise en œuvre peut être différente.

Pour que cela fonctionne, nous devons connecter le composant React à Redux et lier l'action au composant à l'aide de la bibliothèque Redux. Une fois terminé, nous pouvons simplement appeler this.props.getRestaurants(), qui à son tour gérera toutes les tâches ci-dessus et mettra à jour la vue en fonction du réducteur.

Pour son évolutivité, Redux Thunk peut être utilisé pour des applications qui n'impliquent pas de contrôle complexe des actions asynchrones. De plus, il fonctionne de manière transparente avec d'autres bibliothèques, comme décrit dans le sujet dans la section suivante.

Cependant, il est encore un peu difficile d'effectuer certaines tâches à l'aide de Redux Thunk. Par exemple, nous devons mettre en pause l'opération de récupération intermédiaire, ou autoriser uniquement les derniers appels lorsqu'il y a plusieurs appels de tels, ou si d'autres API obtiennent ces données et que nous devons annuler.

Nous pouvons toujours les implémenter, mais il sera plus compliqué à exécuter avec précision. Par rapport aux autres bibliothèques, la clarté du code des tâches complexes sera légèrement pire et sera plus difficile à entretenir.

en utilisant redux-saga

Avec le middleware Redux-Saga, nous pouvons obtenir l'avantage supplémentaire pour aborder la plupart des fonctionnalités ci-dessus. Redux-Saga est développé sur la base du générateur ES6.

redux-saga fournit une API qui aide à atteindre les objectifs suivants:

  • Bloquer des événements, bloquant les fils sur la même ligne jusqu'à ce que certaines opérations soient terminées
  • événements non bloquants, ce qui rend le code asynchrone
  • Gérer la concurrence entre plusieurs demandes asynchrones
  • Pause / étranglement / décrocher toute action

Comment fonctionne Saga?

Saga utilise une combinaison de générateur ES6 et d'API asynchronisée / attendre pour simplifier les opérations asynchrones. Il fait essentiellement son travail sur ses fils séparés où nous pouvons passer plusieurs appels d'API. Nous pouvons utiliser leur API pour rendre chaque appel synchrone ou asynchrone, selon le cas d'utilisation. L'API offre la possibilité de faire attendre un fil sur la même ligne jusqu'à ce que la demande renvoie une réponse. En dehors de cela, cette bibliothèque fournit de nombreuses autres API, qui rendent les demandes d'API très faciles à gérer.

Considérons notre exemple précédent: si nous initialisons une saga et la configurons avec Redux en fonction de ce qui est mentionné dans sa documentation, nous pouvons effectuer ce qui suit:

userDetails: {
  …
  city: 'city',
  …
};
Copier après la connexion
Copier après la connexion

Donc, si nous le distribuons en utilisant une action simple de type FETCH_RESTAURANTS, le middleware Saga écoutera et répondra. En fait, aucune action n'est utilisée par le middleware. Il écoute et effectue simplement d'autres tâches, et distribue de nouvelles actions si nécessaire. En utilisant cette architecture, nous pouvons distribuer plusieurs demandes, chacune décrivant:

  • Quand la première demande commencera-t-elle?
  • Quand la première demande sera-t-elle terminée
  • Quand la deuxième demande commencera-t-elle?

et ainsi de suite.

De plus, vous pouvez voir les avantages de fetchRestaurantSaga(). Nous utilisons actuellement l'API call pour implémenter les appels de blocage. Saga fournit d'autres API, telles que fork(), qui implémente les appels non bloquants. Nous pouvons combiner des appels de blocage et non bloquant pour maintenir une structure adaptée à notre application.

avec évolutivité, l'utilisation de la saga est bénéfique:

  • Nous pouvons construire et regrouper la saga en fonction de toute tâche spécifique. Nous pouvons déclencher une saga d'une autre saga en distribuant simplement une action.
  • Puisqu'il s'agit d'un middleware, l'action que nous avons écrite sera un objet JS normal, contrairement à Thunk.
  • Puisque nous mettons la logique métier à l'intérieur de Saga (qui est un middleware), il serait beaucoup plus facile de comprendre la partie réagi si nous savons de quoi Saga est capable.
  • Les erreurs
  • peuvent être facilement surveillées et distribuées au stockage via le mode Try / Catch.

en utilisant redux-observables

Comme indiqué dans sa documentation, "Epic est la primitive principale de la section" obstatoire ":

redux-observable"
  1. EPIC est une fonction qui reçoit le flux d'action et renvoie le flux d'action. Autrement dit, Epic s'exécute en parallèle avec le canal de distribution Redux normal, après que le réducteur les a reçues.
  2. L'action est toujours exécutée par un réducteur avant que Epic ne les reçoive. EPIC reçoit et ne sort qu'un autre flux d'action. Ceci est similaire à Redux-Saga, car aucune des actions n'est utilisée par middleware. Il écoute et effectue d'autres tâches.

Pour notre tâche, nous pouvons simplement écrire le code suivant:

userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Au début, cela peut sembler un peu déroutant. Cependant, plus vous comprenez RXJS, plus il est facile de créer une épopée.

Comme la saga, nous pouvons distribuer plusieurs actions, chacune décrivant dans quelle partie de la chaîne de demande d'API dans laquelle se trouve le thread.

En termes d'évolutivité, nous pouvons diviser ou combiner Epic en fonction d'une tâche spécifique. Par conséquent, cette bibliothèque peut aider à créer des applications évolutives. Si nous comprenons le modèle observable d'écriture de code, la clarté du code est bonne.

mes préférences

Comment déterminer la bibliothèque à utiliser? Cela dépend de la complexité de nos demandes d'API.

Comment choisir entre redux-saga et redux-observable? Cela dépend du générateur d'apprentissage ou RXJS. Les deux sont des concepts différents, mais tout aussi bons. Je suggère d'essayer les deux de voir lequel est le meilleur pour vous.

Où met la logique métier pour le traitement des API? Il est préférable de le mettre avant le réducteur, mais pas dans la composante. La meilleure façon est dans le middleware (en utilisant la saga ou observable).

Vous pouvez lire plus d'articles de développement React à CodeBrahma.

FAQ sur les opérations asynchrones dans les applications React-Redux

Quel est le rôle du middleware dans la gestion des opérations asynchrones dans Redux?

Le middleware in redux joue un rôle crucial dans la gestion des opérations asynchrones. Il fournit un point d'extension tiers entre l'action de distribution et l'action arrive au réducteur. Le middleware peut être utilisé pour enregistrer, modifier et même annuler des actions, ainsi que pour distribuer d'autres actions. Dans le contexte des opérations asynchrones, le middleware comme Redux Thunk ou Redux vous permet d'écrire des créateurs d'action qui renvoient les fonctions au lieu de l'action. Cette fonction peut ensuite être utilisée pour retarder la distribution d'une action ou pour ne distribuer une action que lorsqu'une condition spécifique est remplie.

Comment Redux Thunk aide-t-il à gérer les opérations asynchrones?

Redux Thunk est un middleware qui vous permet d'écrire des créateurs d'action qui renvoient les fonctions au lieu de l'action. Thunk peut être utilisé pour retarder la distribution des actions ou pour distribuer des actions uniquement lorsque certaines conditions sont remplies. Cette fonctionnalité en fait un excellent outil pour gérer les opérations asynchrones dans Redux. Par exemple, vous pouvez distribuer une action pour indiquer le début d'un appel API, puis distribuer une autre action lorsque l'appel renvoie les données ou le message d'erreur.

Quelle est la différence entre Redux Thunk et Redux Saga?

Redux Thunk et Redux Saga sont tous deux du middleware pour gérer les effets secondaires dans Redux, y compris les opérations asynchrones. La principale différence entre les deux est leur approche. Redux Thunk utilise des fonctions de rappel pour gérer les opérations asynchrones, tandis que Redux Saga utilise des fonctions de générateur et des méthodes plus déclaratives. Cela rend Redux Saga plus puissant et plus flexible, mais aussi plus complexe. Si votre application a des opérations asynchrones simples, Redux Thunk peut suffire. Cependant, pour des scénarios plus complexes impliquant des conditions de course, une annulation et une logique IF-Else, la saga Redux peut être un meilleur choix.

Comment gérer les erreurs dans les opérations asynchrones dans Redux?

L'action peut être distribuée lorsqu'une erreur se produit pendant une opération asynchrone pour gérer la gestion des erreurs en fonctionnement asynchrone dans Redux. Cette action peut prendre son message d'erreur comme charge utile. Vous pouvez ensuite gérer cette action dans le réducteur pour mettre à jour l'état avec le message d'erreur. De cette façon, un message d'erreur peut être affiché à l'utilisateur ou enregistré pour débogage.

Comment tester l'action asynchrone dans Redux?

Les actions asynchrones dans Redux peuvent être testées en moquetant Redux Storage et API. Pour le stockage Redux, vous pouvez utiliser des bibliothèques comme redux-mock-store. Pour les appels API, vous pouvez utiliser des bibliothèques comme fetch-mock ou nock. Dans vos tests, vous pouvez distribuer une action asynchrone, puis affirmer que l'action attendue a été distribuée avec la charge utile correcte.

Comment annuler les opérations asynchrones dans Redux?

Le middleware comme Redux Saga peut être utilisé pour annuler les opérations asynchrones dans Redux. Redux Saga utilise des fonctions de générateur, qui peuvent être annulées à l'aide de l'effet cancel. Lorsque l'effet cancel est donné, la saga sera annulée de son point de démarrage jusqu'à ce que l'effet actuel soit annulé.

Comment gérer les conditions de course dans les opérations asynchrones à Redux?

Le middleware comme Redux Saga peut être utilisé pour gérer les conditions de course dans les opérations asynchrones dans Redux. Redux Saga fournit des effets comme takeLatest et takeEvery qui peuvent être utilisés pour gérer les actions simultanées. Par exemple, si la tâche SAGA précédemment démarrée est toujours en cours d'exécution lorsqu'une nouvelle action est distribuée, takeLatest annule la tâche.

Comment utiliser async / attendre avec redux thunk?

redux Thunk supporte nativement l'async / attendre. Dans votre créateur d'action, vous pouvez retourner des fonctions asynchrones au lieu de fonctions régulières. À l'intérieur de cette fonction asynchrone, vous pouvez utiliser Async / Await pour gérer les opérations asynchrones. Lorsque l'opération asynchrone est terminée, la fonction dispatch peut être appelée à l'aide de l'objet Action.

Comment gérer l'état de chargement dans les opérations asynchrones dans Redux?

L'état de chargement dans les opérations asynchrones dans Redux peut être géré en distribuant des actions avant et après les opérations asynchrones. L'action distribuée avant l'opération peut définir l'état de charge sur true, et l'action distribuée après l'opération peut la définir sur False. Dans votre réducteur, vous pouvez gérer ces actions pour mettre à jour l'état de charge dans le stockage.

Comment gérer les effets secondaires dans Redux?

Les effets secondaires de Redux peuvent être manipulés à l'aide de middleware comme Redux Thunk ou Redux Saga. Ces middleware vous permet d'écrire des créateurs d'action qui renvoient les fonctions au lieu de l'action. Cette fonction peut être utilisée pour effectuer des effets secondaires tels que les opérations asynchrones, l'exploitation forestière et la distribution conditionnellement.

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 de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal