Maison interface Web js tutoriel Chunk-Busters : Ne traversez pas les ruisseaux !

Chunk-Busters : Ne traversez pas les ruisseaux !

Dec 02, 2024 am 05:00 AM

⚠️ Si vous souffrez de photosensibilité, vous voudrez probablement ignorer cela.
Voir l'image statique ci-dessous, ces lumières commenceront à clignoter très rapidement !

Chunk-Busters: Don’t cross the Streams!

Comment fonctionne Internet ?

Souvenez-vous du titre… nous parlons ici de streams.

Je pourrais parler de protocoles, de paquets, d'ordre, d'acks et de nacks… mais nous parlons ici de flux, et comme vous l'avez probablement deviné (je crois en vous =D) avec les flux… c'est soit binaire, soit chaînes.

Oui, les chaînes sont compressées avant d'être envoyées… mais pour ce qui nous importe habituellement lors du développement front et backend… les chaînes et les binaires.

Dans les exemples suivants, j'utiliserai des flux JS.

Bien que Node ait ses propres implémentations héritées, nous avons des moyens de gérer les flux qui contiennent le même code, que ce soit au début ou à la fin.

D'autres langages ont leur façon de gérer les flux, mais comme vous le verrez… la partie code proprement dite pour gérer cela n'était pas si compliquée (pour ne pas dire qu'il ne se passe pas de choses complexes).

L'exemple de problème

Vous disposez d'une interface qui doit consommer des données provenant de plusieurs sources.

Bien que vous puissiez accéder à chaque source individuellement via son IP/port, vous les placez derrière une passerelle API pour faciliter l'utilisation et le contrôle.

Le dépôt

Vérifiez le dépôt sur le lien, apprenez-y à l'exécuter vous-même pour pouvoir jouer avec.

https://github.com/Noriller/chunk-busters

La vidéo

Version vidéo à suivre :

https://youtu.be/QucaOfFI0fM

v0 - l'implémentation naïve

Vous avez les sources, vous récupérez, attendez et effectuez le rendu. Rincez et répétez.

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
Copier après la connexion
Copier après la connexion

Vous pensez peut-être que personne ne fera réellement ça…

Dans cet exemple, il est clair que quelque chose ne va pas, mais ce n'est pas si difficile de tomber dans ce piège.

L’évidence : c’est lent. Vous devez tirer et attendre chaque demande et si c'est lent… vous devez attendre.

v1 - la version impatiente

Vous savez que vous ne voulez pas attendre chaque demande individuellement… alors vous lancez toutes et attendez qu'elles se terminent.

await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
Copier après la connexion
Copier après la connexion

C'est ce que vous faites probablement, alors c'est bien, non ?

Je veux dire, sauf si vous avez UNE seule requête qui est lente… cela signifierait que même si toutes les autres sont déjà terminées… vous devrez quand même attendre que celle-là se termine.

v2 - la version la plus intelligente et la plus enthousiaste

Vous savez que certaines requêtes peuvent être plus lentes, donc vous lancez toujours toutes et attendez, mais au fur et à mesure qu'elles arrivent, vous faites déjà quelque chose avec le résultat lorsque cela est possible, donc quand la dernière arrive, les autres sont déjà terminées.

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
Copier après la connexion
Copier après la connexion

Cela DOIT être la meilleure solution, n'est-ce pas ?

Hmm… quelque chose de bizarre ?

v3 - Je t'ai menti… voici à quoi devrait ressembler la v1

Vous vous souvenez de la v1 ? Ouais… voilà à quoi ça devrait ressembler :

Il s'avère qu'il y a une limite au nombre de connexions que vous pouvez avoir avec exactement le même point de terminaison dans http/1 et pas seulement… cela dépend du navigateur et chaque navigateur peut avoir des limites différentes.

Vous pourriez penser à simplement utiliser http/2 et mettre un terme à cela… mais même si c'était une bonne solution, vous devez toujours gérer plusieurs points de terminaison dans le frontend.

Existe-t-il au moins une bonne solution pour cela ?

v4 - entrez dans les flux !

Revoyons la v0 mais en utilisant des flux…

Vous êtes intelligent, donc vous vous attendiez probablement à cela puisque l'avertissement l'a un peu gâché… mais oui… ce que vous voyiez auparavant n'était pas toutes les données générées par le backend.

Quoi qu'il en soit… au fur et à mesure que nous récupérons, nous rendons.

await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
Copier après la connexion
Copier après la connexion

Si nous tapons plutôt sur le flux à venir, nous pouvons faire quelque chose avec les morceaux de données au fur et à mesure qu'ils arrivent. (Oui ! Aimez Chat GPT et autres.)

Même si la v0 est la pire façon de gérer ce problème, elle est grandement améliorée en utilisant les flux. Vous pouvez tromper l'utilisateur en montrant quelque chose, n'importe quoi, même si le temps d'attente total est le même.

v5 - v1, encore une fois, mais avec des streams !

Le problème http/1 est toujours d'actualité, mais encore une fois, vous pouvez déjà voir les choses telles qu'elles viennent.

Ouais… je ne peux plus retarder ça… alors…

v6 - une API pour les gouverner tous !

Ou… peut-être que je peux ?

Vous voyez, le frontend a dû gérer trop de choses… si nous pouvons décharger cela vers le backend, alors vous pouvez avoir un seul point de terminaison qui gérera toutes les sources.

Cela résout la complexité du frontend et les problèmes http/1.

await Promise.all([
  fetch1().then(handleResult),
  fetch2().then(handleResult),
  ...
  fetch9().then(handleResult),
]);
Copier après la connexion


// usually we do this:
await fetch(...).then((res) => {
  // this json call accumulate all the response
  // that later is returned for you to use
  return res.json()
})
Copier après la connexion

v7 - et enfin… une API, plusieurs sources et streaming.

Nous appelons une API, qui appellera toutes les sources, diffusera les données, les gérera et les transmettra au front qui, à son tour, restituera les données au fur et à mesure qu'elles arrivent.

Le code utilisé pour cela est fondamentalement le même au recto et au verso :

await fetchAll();
handleAllResults(results);
Copier après la connexion

Oui… c'est tout (comme le dit l'exemple le plus basique et le plus simple).

Nous ajoutons la chaîne arrivant dans un tampon, l'analysons, vérifions s'il y a un morceau utilisable, l'utilisons et l'oublions. Cela signifie que vous pourriez recevoir/consommer des To de données… un morceau à la fois, avec peu de RAM.

Je sais à quoi tu penses… et c'est stupide… c'est aussi de la folie…

MOOOOOOOOM je veux des Websockets !

Non chérie, nous avons des websockets à la maison !

Websockets à la maison : la suite ?

v8 - ce n'est stupide que si ça ne marche pas

Vous êtes intelligent, vous pensiez que si la source génère toujours des données… alors peut-être pourrions-nous mettre à jour certaines variables…

De cette façon, vous pouvez conserver la connexion utilisée pour obtenir plus de données ou modifier quelque chose par rapport à ce qu'elle génère.

Oui… je suppose que vous pourriez faire ça… et j'ai fait l'exemple sur votre insistance. =D

Pourtant… c’est une idée stupide, je ne sais pas où/si elle peut être utilisée dans un environnement de production réel. Peut-être que si vous voyagez dans le temps jusqu'à cette phase JS délicate entre MPA et Ajax où vous aviez suffisamment d'interactivité, mais pas assez de connexions au même serveur (certains navigateurs avaient une limite de seulement 2 !), alors peut-être ?

A part ça, aucune idée. Si c’est le cas… faites-le-moi savoir.

Dans l'exemple ci-dessus, attention au panneau central, notamment à la "bordure de progression" : vous pouvez voir que l'on continue de se mettre à jour. Si vous ouvriez l'onglet réseau, vous verriez que la connexion GET n'est jamais fermée avant la fin. Vous verriez également plusieurs autres requêtes qui changent ce que faisait cette connexion, toujours active… tout cela avec vanilla http/1.

Quelle est la prochaine étape ?

Chaîne vs JSON

Cet exemple est le plus basique que j'ai pu faire. J'utilise même des chaînes simples au lieu de JSON car c'est plus facile à analyser.

Pour utiliser JSON, vous devez accumuler la chaîne (nous devons JSON.stringify la réponse du backend pour une raison).

Ensuite, vérifiez où le casser, puis analysez cette valeur ou analysez au fur et à mesure.

Pour le premier, pensez NDJSON : au lieu d'un tableau JSON, vous séparez les objets avec de nouvelles lignes, vous pourrez alors "plus facilement" trouver où casser, puis JSON.parser chacun et utiliser l'objet.

Pour ce dernier, vous analysez au fur et à mesure comme dans : vous savez que vous êtes dans un tableau, maintenant c'est un objet, ok première clé, maintenant c'est la valeur de la clé, clé suivante, sautez ça, clé suivante… et ainsi de suite… ce n'est pas quelque chose de trivial à faire manuellement, mais c'est comme passer de l'attente puis du rendu au rendu pendant que vous attendez, c'est tout… sauf… à une échelle encore plus petite.

Gestion des erreurs

Les gens aiment héberger des exemples, celui-ci, vous devez l'exécuter vous-même… J'espère que la raison pour laquelle vous n'hébergez pas l'exemple quelque part est claire maintenant, mais une autre raison est que nous ne nous attendons à aucune erreur ici, et si vous deviez le faire ajoutez les erreurs réseau par-dessus tout… eh bien…

Les erreurs doivent être gérées, mais elles ajoutent une autre couche de complexité.

Devriez-vous l’utiliser ?

Peut-être… tu peux le dire dépend

Il y a des endroits où le streaming est la réponse, mais dans la plupart des cas… wait json suffit (sans parler de plus facile).

Mais l'apprentissage des flux ouvre des voies pour résoudre certains problèmes, que ce soit au niveau du frontend ou du backend.

Dans le frontend, vous pouvez toujours l'utiliser pour « tromper » l'utilisateur. Au lieu d'afficher des spinners partout, vous pouvez montrer quelque chose au fur et à mesure, puis en montrer davantage au fur et à mesure, même si cela prend un certain temps. Tant que vous n'empêchez pas l'utilisateur d'interagir avec lui… vous pouvez même créer quelque chose de « plus lent » que de simplement montrer aux spinners l'impression que c'est bien plus rapide que tout en fait plus rapide .

Dans le backend, vous pouvez économiser de la RAM puisque vous pouvez simplement analyser chaque bloc de données au fur et à mesure qu'il arrive, que ce soit depuis l'avant, une base de données ou tout autre élément intermédiaire. Gérez les données selon vos besoins et envoyez-les sans avoir à attendre la totalité de la charge utile, ce qui entraînerait une erreur MOO (mémoire insuffisante). Des Go, voire des To, de données… bien sûr, pourquoi pas ?

Sortie

React est-il lent ? Cet exemple d'interface a été réalisé avec React et à part la chose « principale » qui se passe avec toutes les « lumières » clignotantes, il se passe beaucoup d'autres choses.

Oui… si vous allez assez vite, l’exemple ne peut pas suivre et commence à se figer. Mais comme il y a facilement des milliers de rendus par minute… je pense que c'est suffisant pour la plupart des applications.

Et vous pouvez toujours améliorer les performances : pour la « bordure de progression », j'ai utilisé des valeurs différées pour la rendre plus fluide si vous devez en enregistrer dans les rendus… Je pourrais faire cela et d'autres améliorations de performances pour les « lumières » et le titre, mais cela empêcherait simplement les « lumières » de clignoter la plupart du temps (ce qui ne ferait pas une belle démo), et aussi le soulignement « électrique » dans le titre ne serait pas aussi amusant que ça. est.

Dans cet exemple, toutes ces « améliorations » ne seraient pas idéales, mais pour des applications normales... vous pouvez lui faire gérer beaucoup de choses. Et si vous avez besoin de quelque chose de plus, utilisez dans ce cas une autre solution.

Conclusion

Ajoutez des streams à votre arsenal… ce n'est peut-être pas une solution panacée, mais cela vous sera sûrement utile un jour.

Et si vous voulez faire quelque chose avec et que vous voulez de l’aide, eh bien… appelez-moi peut-être. =P

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

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

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

<🎜>: Grow A Garden - Guide de mutation complet
3 Il y a quelques semaines By DDD
<🎜>: Bubble Gum Simulator Infinity - Comment obtenir et utiliser les clés royales
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Système de fusion, expliqué
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Comment déverrouiller le grappin
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1665
14
Tutoriel PHP
1269
29
Tutoriel C#
1249
24
Moteurs JavaScript: comparaison des implémentations Moteurs JavaScript: comparaison des implémentations Apr 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.

Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Apr 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.

De C / C à JavaScript: comment tout cela fonctionne De C / C à JavaScript: comment tout cela fonctionne Apr 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.

Javascript et le web: fonctionnalité de base et cas d'utilisation Javascript et le web: fonctionnalité de base et cas d'utilisation Apr 18, 2025 am 12:19 AM

Les principales utilisations de JavaScript dans le développement Web incluent l'interaction client, la vérification du formulaire et la communication asynchrone. 1) Mise à jour du contenu dynamique et interaction utilisateur via les opérations DOM; 2) La vérification du client est effectuée avant que l'utilisateur ne soumette les données pour améliorer l'expérience utilisateur; 3) La communication de rafraîchissement avec le serveur est réalisée via la technologie AJAX.

JavaScript en action: Exemples et projets du monde réel JavaScript en action: Exemples et projets du monde réel Apr 19, 2025 am 12:13 AM

L'application de JavaScript dans le monde réel comprend un développement frontal et back-end. 1) Afficher les applications frontales en créant une application de liste TODO, impliquant les opérations DOM et le traitement des événements. 2) Construisez RestulAPI via Node.js et Express pour démontrer les applications back-end.

Comprendre le moteur JavaScript: détails de l'implémentation Comprendre le moteur JavaScript: détails de l'implémentation Apr 17, 2025 am 12:05 AM

Comprendre le fonctionnement du moteur JavaScript en interne est important pour les développeurs car il aide à écrire du code plus efficace et à comprendre les goulots d'étranglement des performances et les stratégies d'optimisation. 1) Le flux de travail du moteur comprend trois étapes: analyse, compilation et exécution; 2) Pendant le processus d'exécution, le moteur effectuera une optimisation dynamique, comme le cache en ligne et les classes cachées; 3) Les meilleures pratiques comprennent l'évitement des variables globales, l'optimisation des boucles, l'utilisation de const et de locations et d'éviter une utilisation excessive des fermetures.

Python vs JavaScript: communauté, bibliothèques et ressources Python vs JavaScript: communauté, bibliothèques et ressources Apr 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.

Python vs JavaScript: environnements et outils de développement Python vs JavaScript: environnements et outils de développement Apr 26, 2025 am 12:09 AM

Les choix de Python et JavaScript dans les environnements de développement sont importants. 1) L'environnement de développement de Python comprend Pycharm, Jupyternotebook et Anaconda, qui conviennent à la science des données et au prototypage rapide. 2) L'environnement de développement de JavaScript comprend Node.js, VScode et WebPack, qui conviennent au développement frontal et back-end. Le choix des bons outils en fonction des besoins du projet peut améliorer l'efficacité du développement et le taux de réussite du projet.

See all articles