Maison  >  Article  >  interface Web  >  Comprendre les flux dans Node.js

Comprendre les flux dans Node.js

青灯夜游
青灯夜游avant
2020-11-19 17:48:582899parcourir

Comprendre les flux dans Node.js

Recommandations associées : "Tutoriel nodejs"

Pour la plupart des étudiants ayant une expérience back-end, l'objet Stream est un objet raisonnable et courant , mais Stream, camarade de classe front-end, n'est pas si pris pour acquis. Il existe même un article avec plus de 9 000 étoiles sur github présentant ce qu'est Stream - stream-handbook (https://link.zhihu.com/?target=https% 3A //github.com/substack/stream-handbook). Afin de mieux comprendre Stream, résumons-le brièvement sur la base de cet article.

Qu'est-ce que Stream

Le flux est un concept très courant et important dans les systèmes Unix. Dans la terminologie, le flux est une abstraction des périphériques d'entrée et de sortie.

ls | grep *.js

Nous rencontrons souvent du code comme celui-ci lors de l'écriture de scripts. Utilisez | pour connecter deux commandes et transmettre le résultat de la commande précédente comme paramètre de cette dernière. , les données sont transmises comme l'eau dans un tuyau, et chaque commande est comme un processeur qui effectue un certain traitement sur les données, donc | est appelé "symbole du tuyau ".

Plusieurs types de Stream dans NodeJS

Du point de vue du programme, un flux est des données dirigées, qui peuvent être divisées en trois types selon la direction du flux

  • Flux de l'appareil vers le programme : lisible

  • Flux du programme vers l'appareil : inscriptible

  • Bidirectionnel : duplex , transform

Les opérations de flux de NodeJS sont encapsulées dans le module Stream, qui est également référencé par plusieurs modules principaux. Selon la philosophie Unix : tout est un fichier, la plupart des traitements de fichiers dans NodeJS utilisent des flux pour compléter les

  • fichiers ordinaires

  • fichiers de périphérique ( stdin , stdout)

  • Fichiers réseau (http, net)

Il y a un point de connaissance qui est facilement négligé : tous les flux dans NodeJS sont tous instances de EventEmitter.

Petit exemple

Lorsque nous écrivons un programme, nous avons soudainement besoin de lire un certain fichier de configuration config.json À ce stade, nous analyserons brièvement le

    données : Contenu de config.json
  • Direction : Périphérique (fichier de disque physique) -> Programme NodeJS
Nous devons utiliser un flux lisible pour ce faire

const fs = require('fs');
const FILEPATH = '...';

const rs = fs.createReadStream(FILEPATH);
Nous créons facilement un flux lisible grâce à la méthode

fournie par le module fs À ce stade, le contenu de createReadStream()config.json circule de l'appareil vers le programme. Nous n'avons pas utilisé le module Stream directement car fs a déjà référencé le module Stream en interne et l'a encapsulé.

Une fois que nous avons les données, nous devons les traiter. Par exemple, nous devons écrire sur un certain chemin DEST. À ce stade, nous avons besoin d'un flux inscriptible pour permettre aux données de circuler du programme vers. l'appareil.

const ws = fs.createWriteStream(DEST);
Maintenant que nous avons deux flux, c'est-à-dire deux processeurs de données, comment pouvons-nous connecter les flux via le symbole pipe de type Unix

 ? Dans NodeJS, le symbole du tuyau est la méthode |. pipe()

const fs = require('fs');
const FILEPATH = '...';

const rs = fs.createReadStream(FILEPATH);
const ws = fs.createWriteStream(DEST);

rs.pipe(ws);
De cette façon, nous utilisons des flux pour implémenter une simple fonction de copie de fichier. Le principe d'implémentation de la méthode pipe() sera mentionné plus tard, mais il y a une chose à noter : les données doivent être redirigées depuis de l'amont vers l'aval, c'est-à-dire Pipe d'un flux lisible vers un flux inscriptible.

Traiter les données

Les flux lisibles et inscriptibles sont mentionnés ci-dessus. Nous les appelons processeurs. En fait, ce n'est pas approprié car nous ne traitons rien, nous lisons simplement les données, puis. Stocker des données.

Si nécessaire, modifiez toutes les lettres du fichier

package.json local en minuscules et enregistrez-le dans le fichier package-lower.json dans le même répertoire.

À l'heure actuelle, nous devons utiliser un flux bidirectionnel. Supposons que nous ayons un flux inférieur qui gère spécifiquement la conversion des caractères en minuscules. Ensuite, le code écrit ressemble probablement à ceci

const fs = require('fs');

const rs = fs.createReadStream('./package.json');
const ws = fs.createWriteStream('./package-lower.json');

rs.pipe(lower).pipe(ws);
At. cette fois, nous pouvons voir pourquoi le flux connecté par pipe() est appelé un processeur. D'après ce qui est dit ci-dessus, le tuyau doit être redirigé d'un flux lisible vers un flux inscriptible :

    rs -> lower : lower est en aval, donc lower doit être un flux inscriptible
  • lower -> ws : Relativement parlant, lower est en amont, donc lower doit être un flux lisible
C'est un peu de raisonnement, mais cela peut satisfaire. Le plus bas dont nous avons besoin doit être un flux bidirectionnel. Nous mentionnerons plus tard l'utilisation spécifique du duplex ou de la transformation.

Bien sûr, si nous avons des actions de traitement supplémentaires, telles que des lettres qui doivent être converties en codes ASCII, en supposant qu'il existe un flux ascii, alors notre code peut être

rs.pipe(lower).pipe(acsii).pipe(ws);
De même, ascii doit également être un flux bidirectionnel. La logique de ce traitement est très claire, donc en plus d'un code clair, quels sont les avantages de l'utilisation des flux ?

Pourquoi Stream doit être utilisé

Il existe un scénario dans lequel un utilisateur doit regarder une vidéo en ligne. Supposons que nous renvoyions le contenu d'un film à l'utilisateur via une requête HTTP, le code peut alors être écrit. comme ça

const http = require('http');
const fs = require('fs');

http.createServer((req, res) => {
   fs.readFile(moviePath, (err, data) => {
      res.end(data);
   });
}).listen(8080);

这样的代码又两个明显的问题

  • 电影文件需要读完之后才能返回给客户,等待时间超长

  • 电影文件需要一次放入内存中,相似动作多了,内存吃不消

用流可以讲电影文件一点点的放入内存中,然后一点点的返回给客户(利用了 HTTP 协议的 Transfer-Encoding: chunked 分段传输特性),用户体验得到优化,同时对内存的开销明显下降

const http = require('http');

const fs = require('fs');

http.createServer((req, res) => {

   fs.createReadStream(moviePath).pipe(res);

}).listen(8080);

除了上述好处,代码优雅了很多,拓展也比较简单。比如需要对视频内容压缩,我们可以引入一个专门做此事的流,这个流不用关心其它部分做了什么,只要是接入管道中就可以了

const http = require('http');

const fs = require('fs');

const oppressor = require(oppressor);

http.createServer((req, res) => {

   fs.createReadStream(moviePath)

      .pipe(oppressor)

      .pipe(res);

}).listen(8080);

可以看出来,使用流后,我们的代码逻辑变得相对独立,可维护性也会有一定的改善,关于几种流的具体使用方式且听下回分解。

更多编程相关知识,请访问:编程视频课程!!

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer