Close Menu
Soshace Digital Blog

    Subscribe to Updates

    Get The Latest News, Updates, And Amazing Offers

    What's Hot
    Entrepreneurs

    Developing the Proper Business Performance

    JavaScript

    Fermentum Dui Faucibus Bnornare Quam Viverra Orci

    Tips

    Who is a Developer Advocate?

    Important Pages:
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Today's Picks:
    • Scaling Success: Monitoring Indexation of Programmatic SEO Content
    • Leveraging Influencers: Key Drivers in New Product Launches
    • How Privacy-First Marketing Will Transform the Industry Landscape
    • The Impact of Social Proof on Thought Leadership Marketing
    • Balancing Value-Driven Content and Promotional Messaging Strategies
    • Top Influencer Marketing Platforms to Explore in 2025
    • Emerging Trends in Marketing Automation and AI Tools for 2023
    • Strategies to Mitigate Duplicate Content in Programmatic SEO
    Sunday, September 28
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Soshace Digital Blog
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Services
    • SaaS & Tech

      Maximizing Efficiency: How SaaS Lowers IT Infrastructure Costs

      August 27, 2025

      Navigating Tomorrow: Innovations Shaping the Future of SaaS

      August 27, 2025

      Maximizing Impact: Strategies for SaaS & Technology Marketing

      August 27, 2025
    • AI & Automation

      Enhancing Customer Feedback Analysis Through AI Innovations

      August 27, 2025

      Navigating the Impact of AI on SEO and Search Rankings

      August 27, 2025

      5 Automation Hacks Every Home Service Business Needs to Know

      May 3, 2025
    • Finance & Fintech

      Critical Missteps in Finance Marketing: What to Avoid

      August 27, 2025

      Analyzing Future Fintech Marketing Trends: Insights Ahead

      August 27, 2025

      Navigating the Complex Landscape of Finance and Fintech Marketing

      August 27, 2025
    • Legal & Compliance

      Exploring Thought Leadership’s Impact on Legal Marketing

      August 27, 2025

      Maximizing LinkedIn: Strategies for Legal and Compliance Marketing

      August 27, 2025

      Why Transparency Matters in Legal Advertising Practices

      August 27, 2025
    • Medical Marketing

      Enhancing Online Reputation Management in Hospitals: A Guide

      August 27, 2025

      Analyzing Emerging Trends in Health and Medical Marketing

      August 27, 2025

      Exploring Innovative Content Ideas for Wellness Blogs and Clinics

      August 27, 2025
    • E-commerce & Retail

      Strategic Seasonal Campaign Concepts for Online and Retail Markets

      August 27, 2025

      Emerging Trends in E-commerce and Retail Marketing Strategies

      August 27, 2025

      Maximizing Revenue: The Advantages of Affiliate Marketing for E-Commerce

      August 27, 2025
    • Influencer & Community

      Leveraging Influencers: Key Drivers in New Product Launches

      August 27, 2025

      Top Influencer Marketing Platforms to Explore in 2025

      August 27, 2025

      Key Strategies for Successful Influencer Partnership Negotiations

      August 27, 2025
    • Content & Leadership

      The Impact of Social Proof on Thought Leadership Marketing

      August 27, 2025

      Balancing Value-Driven Content and Promotional Messaging Strategies

      August 27, 2025

      Analyzing Storytelling’s Impact on Content Marketing Effectiveness

      August 27, 2025
    • SEO & Analytics

      Scaling Success: Monitoring Indexation of Programmatic SEO Content

      August 27, 2025

      Strategies to Mitigate Duplicate Content in Programmatic SEO

      August 27, 2025

      Effective Data Visualization Techniques for SEO Reporting

      August 27, 2025
    • Marketing Trends

      How Privacy-First Marketing Will Transform the Industry Landscape

      August 27, 2025

      Emerging Trends in Marketing Automation and AI Tools for 2023

      August 27, 2025

      Maximizing ROI: Key Trends in Paid Social Advertising

      August 27, 2025
    Soshace Digital Blog
    Blog / Programming / 21. Уроки Node.js. Writable Поток Ответа res, Метод pipe. Pt.1
    Programming

    21. Уроки Node.js. Writable Поток Ответа res, Метод pipe. Pt.1

    bragin_paBy bragin_paOctober 25, 2016Updated:May 26, 2024No Comments6 Mins Read
    Facebook Twitter Pinterest Telegram LinkedIn Tumblr Email Reddit
    21. Уроки Node.js. Writable Поток Ответа res, Метод pipe. Pt.1
    Share
    Facebook Twitter LinkedIn Pinterest Email Copy Link

    21-lesson_pt1

    Нашим следующим шагом будет использование потоков для работы с сетевыми соединениями. И начнем мы с отдачи посетителю файлов. Если помните, у нас была такая задача: если посетитель запросит следующий url, то отдать ему файл. Создадим файл pipe.js со следующим кодом (для удобства вы можете скачать код нашего урока в репозитории, так как нам понадобиться HTML файл оттуда) :

    var http = require('http');
    var fs = require('fs');
    
    new http.Server(function(req, res) {
      // res instanceof http.ServerResponse < stream.Writable
    
      if (req.url == '/big.html') {
    
        fs.readFile('big.html', function(err, content) {
          if (err) {
            res.statusCode = 500;
            res.end('Server error');
          } else {
            res.setHeader("Content-type", "text/html; charset=utf-8");
            res.end(content);
          }
        });
    
      }
    }).listen(3000);

    Пример решения этой задачи без потоков может быть таким: читаем файл:

    fs.readFile('big.html', function(err, content) {

    когда тот будет прочитан вызываем callback:

     function(err, content) {
                if (err) {
                    res.statusCode = 500;
                    res.end('Server error');
                } else {
                    res.setHeader("Content-type", "text/html; charset=utf-8");
                    res.end(content);
                }
            });

    дальше при ошибке сообщаем о ней, а если все хорошо, то ставим заголовок, чтобы указать, какой это файл. И записываем содержимое файла в ответ вызовом res.end(content) , который отдает контент и завершает соединение. Это решение в принципе работает, но его проблема – это пожирание памяти, потому что если файл большой, то readFile его сначала считает, а потом вызовет callback. В результате получится, что если клиент медленный, то весь этот считанный контент зависнет в памяти до того, как клиент его получит.

    А что если у нас таких медленных клиентов много? А если файл очень большой? Получается, что сервер почти мгновенно может занять всю доступную память, что совершенно неприемлемо. Чтобы такого не происходило, мы заменим код отдачи файла на принципиально другой, использующий потоки. Мы уже умеем читать из файла при помощи ReadStream:

    var file = new fs.ReadStream('big.html');

    Это будет входным потоком данных. А выходным потоком будет объект ответа res, который является объектом класса http.ServerResponse  наследующим от stream.Writable.

    Общий алгоритм использования потоков для записи сильно отличатся от того,  что мы рассматривали ранее. Он выглядит так:

    scheme
    Вначале мы создаем объект потока. Если у нас http сервер, то этот объект уже создан. Это res. Дальше мы хотим отправить что-то клиенту. Это можно сделать вызовом res.write и передать там наши данные. Обычно это либо буфер, либо строка. Наши данные при этом добавляются к специальному свойству потока, которое называют его буфером.  Если пока этот буфер не очень большой, то данные прибавляются к нему, и write возвращает true, что означает, что мы можем писать еще. При этом обязательство по отсылке данных берет на себя уже сам поток. Как правило, эта отсылка происходит асинхронно.

    Read More:  23. Уроки Node.js. Домены, "асинхронный try..catch". Часть 1.

    Возможен и другой вариант. Например, если мы передали сразу очень много данных, или если буфер уже был чем-то занят, то метод write может вернуть false, который означает, что внутренний буфер потока переполнен и прямо сейчас запись, конечно, можно сделать, но это будет нецелесообразно, потому что в буфере все будет копиться. Поэтому при получении false обычно запись не продолжают, а ждут специального события drain, которое будет сгенерировано потоком, когда он все отошлет, то есть, когда его внутренний буфер опустеет.

    Таким образом можем вызывать write много раз, и когда мы понимаем, что все данные записаны, то мы должны вызвать метод end. Тут тоже можно передать с первым аргументом данные. В этом случае он просто вызовет write . Самая главная задача end – это закончить запись. Поток это делает, при необходимости вызывает внутренние операции закрытия ресурсов (файлов), соединений и т.д. И потом генерирует события finish, который означает, что запись полностью завершена.

    Обращаем ваше внимание, что аналогичное событие у stream.Writable называется end. Это различие неслучайно, потому что есть потоки duplex, которые умеют и читать, и писать. Соответственно, они могут генерировать как одно событие, так и другое.

    Поток в любой момент можно разрушить вызовом метода destroy(). При вызове этого метода работа потока прекращается, и все ассоциированные с ним ресурсы будут освобождены. Конечно, событие finish уже никогда не состоится, потому что это уже успешное окончание работы потока, успешная отдача всех данных.

    Реализуем правильную отдачу файла, используя схему справок как шпаргалку. Будем делать то в отдельной функции, которая будет называться sendFile.
    Она будет принимать один поток для файла и второй поток для ответа.

    Для начала pipe.js будет выглядеть так:

    var http = require('http');
    var fs = require('fs');
    
    new http.Server(function(req, res) {
        // res instanceof http.ServerResponse < stream.Writable
    
        if (req.url == '/big.html') {
    
            var file = new fs.ReadStream('big.html');
            sendFile(file, res);
    
        }
    }).listen(3000);
    
    function sendFile(file, res) {
    
        file.on('readable', write);
    
        function write() {
            var fileContent = file.read();
    
            res.write(fileContent);
        }
    }

    Первое, что мы будем делать с такой функцией – это ждать данных:

    function sendFile(file, res) {  
      
      file.on('readable', write); 
    

    Затем, когда они получены, то внутри обработчика readable читать их и отправлять в ответ:

    function write() {
            var fileContent = file.read();
    
            res.write(fileContent);
        }

    Конечно же, она не выдерживает никакой критики, поскольку в том случае, если клиент пока не может получить эти данные (например, потому что у него медленная скорость соединения), то они зависнут в буфере объекта res:

    res.write(fileContent)

    Таким образом, если файл быстро считан, но пока не отправлен, то он займет большое количество памяти, а этого мы как раз хотели избежать. В этом небольшом коде изложен пример универсального решения этой задачи, скопируйте эту часть кода в замен ранее написанной:

    function sendFile(file, res) {
    
        file.on('readable', write);
    
        function write() {
            var fileContent = file.read(); // read
    
            if (fileContent && !res.write(fileContent)) { // send
    
                file.removeListener('readable', write);
    
                res.once('drain', function() { //wait
                    file.on('readable', write);
                    write();
                });
            }
        }
    
    
    }

    Мы тоже читаем содержимое из файла на событие readable, но мы не просто отправляем его вызовом res.write, а еще и анализируем, что этот вызов вернет. Если res принимает данные очень быстро, то res.write будет возвращать  true. Это означает, что ветка if никогда не выполнится

    if (fileContent && !res.write(fileContent)) {...}

    Соответственно, мы получим read-write,  read-write и т.д.

    Read More:  15. Уроки Node.js. Асинхронная разработка. Введение.

    Более интересный случай, когда  res.write вернул false. То есть, когда буфер переполнен, в этом случае мы временно отказываемся обрабатывать события readableна файле.

    file.removeListener('readable', write);

    Само по себе такое снятие обработчика не означает, что файловый поток перестанет читать данные. Нет, он будет читать данные, но дочитает их до определенного уровня, заполнит свой внутренний буфер объекта файла, и затем, так как никто  не вызывает read, то этот внутренний буфер останется заполнен на определенном уровне, то есть, файловый поток что-то считает и там остановиться. Далее мы дождемся события drain

    res.once('drain', function() {
                    file.on('readable', write);
                    write();
                });

    То есть, когда данные будут успешно отданы в ответ (означает, что мы можем принять что-то еще из файла), мы вновь показываем свой интерес в событиях readable и вызываем метод write сразу. Зачем? Просто потому что, пока мы ждали этого drain, новые данные вполне могли придти. Это означает, что имеет смысл их тут же прочитать:

    var fileContent = file.read();
    

    Вызов read вернет null в том случае, если данных нет. А если есть, то они просто будут обработаны тем же способом, о котором мы говорили раньше в if.

    Получается такая вот своеобразная рекурсивная функция: считать, отправить то, что считано, при необходимости подождать  drain , считать, отправить и подождать, и т.д. по циклу, пока файл не закончится.

    tumblr_ng6oke7J1k1sxr61eo1_1280
    Материалы для статьи взяты из следующего
    скринкаста.

     

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    bragin_pa

      Related Posts

      3. Уроки Express.js. Шаблонизация с EJS: Layout, Block, Partials

      December 16, 2016

      Уроки Express.js . Логгер, Конфигурация, Шаблонизация с EJS. Часть 2.

      December 2, 2016

      2. Уроки Express.js . Логгер, Конфигурация, Шаблонизация с EJS. Часть 1.

      November 24, 2016
      Leave A Reply Cancel Reply

      You must be logged in to post a comment.

      Stay In Touch
      • Facebook
      • Twitter
      • Pinterest
      • Instagram
      • YouTube
      • Vimeo
      Don't Miss
      JavaScript February 19, 2020

      This Is How I Created a Simple App Using React Routing

      react-router is an amazing library. Here’s how to create a simple app using it.

      Using Feature Flags for A/B Testing & Optionally Enable/Disable Features in Your NodeJS Project

      December 25, 2020

      Securing Node.js Applications with JWT and Passport.js

      May 2, 2023

      Node.js Lesson 2: Modules and Exports

      September 7, 2020

      Categories

      • AI & Automation
      • Angular
      • ASP.NET
      • AWS
      • B2B Leads
      • Beginners
      • Blogs
      • Business Growth
      • Case Studies
      • Comics
      • Consultation
      • Content & Leadership
      • CSS
      • Development
      • Django
      • E-commerce & Retail
      • Entrepreneurs
      • Entrepreneurship
      • Events
      • Express.js
      • Facebook Ads
      • Finance & Fintech
      • Flask
      • Flutter
      • Franchising
      • Funnel Strategy
      • Git
      • GraphQL
      • Home Services Marketing
      • Influencer & Community
      • Interview
      • Java
      • Java Spring
      • JavaScript
      • Job
      • Laravel
      • Lead Generation
      • Legal & Compliance
      • LinkedIn
      • Machine Learning
      • Marketing Trends
      • Medical Marketing
      • MSP Lead Generation
      • MSP Marketing
      • NestJS
      • Next.js
      • Node.js
      • Node.js Lessons
      • Paid Advertising
      • PHP
      • Podcasts
      • POS Tutorial
      • Programming
      • Programming
      • Python
      • React
      • React Lessons
      • React Native
      • React Native Lessons
      • Recruitment
      • Remote Job
      • SaaS & Tech
      • SEO & Analytics
      • Soshace
      • Startups
      • Swarm Intelligence
      • Tips
      • Trends
      • Vue
      • Wiki
      • WordPress
      Top Posts

      Create simple POS with React, Node and MongoDB #3: setup E-mail pipeline with add activate on SignUp

      JavaScript January 28, 2020

      Everyday Coding

      Programming August 9, 2016

      HR Tech Conferences Worth Your Time [2019]

      Events August 8, 2019

      Структура организации

      Programming September 22, 2016

      Subscribe to Updates

      Get The Latest News, Updates, And Amazing Offers

      About Us
      About Us

      Soshace Digital delivers comprehensive web design and development solutions tailored to your business objectives. Your website will be meticulously designed and developed by our team of seasoned professionals, who combine creative expertise with technical excellence to transform your vision into a high-impact, user-centric digital experience that elevates your brand and drives measurable results.

      7901 4th St N, Suite 28690
      Saint Petersburg, FL 33702-4305
      Phone: 1(877)SOSHACE

      Facebook X (Twitter) Instagram Pinterest YouTube LinkedIn
      Our Picks
      JavaScript

      React Lesson 13. Part 1: Asynchronous actions

      Blogs

      Effective Recruitment Strategies for Nonprofit Organizations

      Programming

      16. Уроки Node.js. Событийный цикл, библиотека libUV. Часть 1.

      Most Popular

      Broad Topics in Tech Podcasts — Part 4

      Podcasts

      JavaScript Closures and Scoping: Understanding Execution Context and Variable Hoisting

      JavaScript

      Уроки React. Урок 14.

      Programming
      © 2025 Soshace Digital.
      • Home
      • About
      • Services
      • Contact Us
      • Privacy Policy
      • Terms & Conditions

      Type above and press Enter to search. Press Esc to cancel.