Главная страница
Навигация по странице:

  • API Node.js, в которых используются потоки

  • Создание потока для чтения

  • Создание потока для записи

  • Получение данных из потока для чтения

  • Отправка данных в поток для записи

  • Основы работы с MySQL в Node.js

  • Установка пакета Для установки этого пакета воспользуйтесь такой командой: npm install mysql Инициализация подключения к базе данных

  • Выполнение запроса SELECT

  • Выполнение запроса INSERT

  • Закрытие соединения с базой данных

  • О разнице между средой разработки и продакшн-средой

  • Протоколы http и WebSocket Часть 9 работа с файловой системой Часть 10 стандартные модули, потоки, базы данных, node env


    Скачать 1.79 Mb.
    НазваниеПротоколы http и WebSocket Часть 9 работа с файловой системой Часть 10 стандартные модули, потоки, базы данных, node env
    Дата03.03.2019
    Размер1.79 Mb.
    Формат файлаpdf
    Имя файлаee86eb4f-db9f-48d3-8094-c76e14414678.pdf
    ТипПротокол
    #69437
    страница9 из 9
    1   2   3   4   5   6   7   8   9
    Пример работы с потоками
    Традиционный пример работы с потоками демонстрирует чтение файла с диска.
    Сначала рассмотрим код, в котором потоки не используются. Стандартный модуль Node.js ​fs позволяет прочитать файл, после чего его можно передать по протоколу HTTP в ответ на запрос, полученный HTTP-сервером: const http = require('http') const fs = require('fs') const server = http.createServer(function (req, res) { fs.readFile(__dirname + '/data.txt', (err, data) => { res.end(data)
    })
    }) server.listen(3000)

    Метод ​readFile()​, использованный здесь, позволяет прочесть файл целиком. Когда чтение будет завершено, он вызывает соответствующий коллбэк.
    Метод ​res.end(data)​, вызываемый в коллбэке, отправляет содержимое файла клиенту.
    Если размер файла велик, то эта операция займёт немало времени. Вот тот же пример переписанный с использованием потоков: const http = require('http') const fs = require('fs') const server = http.createServer((req, res) => { const stream = fs.createReadStream(__dirname + '/data.txt') stream.pipe(res)
    }) server.listen(3000)
    Вместо того, чтобы ждать того момента, когда файл будет полностью прочитан, мы начинаем передавать его данные клиенту сразу после того, как первая порция этих данных будет готова к отправке.
    Метод pipe()
    В предыдущем примере мы использовали конструкцию вида ​stream.pipe(res)​, в которой вызывается метод файлового потока ​pipe()​. Этот метод берёт данные из их источника и отправляет их в место назначения.
    Его вызывают для потока, представляющего собой источник данных. В данном случае это — файловый поток, который отправляют в HTTP-ответ.
    Возвращаемым значением метода ​pipe()​ является целевой поток. Это очень удобно, так как позволяет объединять в цепочки несколько вызовов метода ​pipe()​: src.pipe(dest1).pipe(dest2)
    Это равносильно такой конструкции: src.pipe(dest1) dest1.pipe(dest2)
    API Node.js, в которых используются потоки
    Потоки — полезный механизм, в результате многие модули ядра Node.js предоставляют стандартные возможности по работе с потоками. Перечислим некоторые из них:
    ● process.stdin​ — возвращает поток, подключённый к ​stdin​.
    ● process.stdout​ — возвращает поток, подключённый к ​stdout​.
    ● process.stderr​ — возвращает поток, подключённый к ​stderr​.
    ● fs.createReadStream()​ — создаёт читаемый поток для работы с файлом.
    ● fs.createWriteStream()​— создаёт записываемый поток для работы с файлом.
    ● net.connect()​ — инициирует соединение, основанное на потоке.
    ● http.request()​ — возвращает экземпляр класса ​http.ClientRequest​, предоставляющий доступ к записываемому потоку.

    ● zlib.createGzip()​ — сжимает данные с использованием алгоритма ​gzip​ и отправляет их в поток.
    ● zlib.createGunzip()​ — выполняет декомпрессию ​gzip​-потока.
    ● zlib.createDeflate()​ — сжимает данные с использованием алгоритма ​deflate​ и отправляет их в поток.
    ● zlib.createInflate()​ — выполняет декомпрессию ​deflate​-потока.
    Разные типы потоков
    Существует четыре типа потоков:
    ● Поток для чтения (​Readable​) — это поток, из которого можно читать данные. Записывать данные в такой поток нельзя. Когда в такой поток поступают данные, они буферизуются до того момента пока потребитель данных не приступит к их чтению.
    ● Поток для записи (​Writable​) — это поток, в который можно отправлять данные. Читать из него данные нельзя.
    ● Дуплексный поток (​Duplex​) — в такой поток можно и отправлять данные и читать их из него. По существу это — комбинация потока для чтения и потока для записи.
    ● Трансформирующий поток (​Transform​) — такие потоки похожи на дуплексные потоки, разница заключается в том, что то, что поступает на вход этих потоков, преобразует то, что из них можно прочитать.
    Создание потока для чтения
    Поток для чтения можно создать и инициализировать, воспользовавшись возможностями модуля stream​: const Stream = require('stream') const readableStream = new Stream.Readable()
    Теперь в поток можно поместить данные, которые позже сможет прочесть потребитель этих данных: readableStream.push('hi!') readableStream.push('ho!')
    Создание потока для записи
    Для того чтобы создать записываемый поток нужно расширить базовый объект ​Writable​ и реализовать его метод ​_write()​. Для этого сначала создадим соответствующий поток: const Stream = require('stream') const writableStream = new Stream.Writable()
    Затем реализуем его метод ​_write()​: writableStream._write = (chunk, encoding, next) => { console.log(chunk.toString()) next()
    }
    Теперь к такому потоку можно подключить поток, предназначенный для чтения: process.stdin.pipe(writableStream)

    Получение данных из потока для чтения
    Для того чтобы получить данные из потока, предназначенного для чтения, воспользуемся потоком для записи: const Stream = require('stream') const readableStream = new Stream.Readable() const writableStream = new Stream.Writable() writableStream._write = (chunk, encoding, next) => { console.log(chunk.toString()) next()
    } readableStream.pipe(writableStream) readableStream.push('hi!') readableStream.push('ho!') readableStream.push(null)
    Команда ​readableStream.push(null)​ сообщает об окончании вывода данных.
    Работать с потоками для чтения можно и напрямую, обрабатывая событие ​readable​: readableStream.on('readable', () => { console.log(readableStream.read())
    })
    Отправка данных в поток для записи
    Для отправки данных в поток для записи используется метод ​write()​: writableStream.write('hey!\n')
    Сообщение потоку для записи о том, что запись данных завершена
    Для того чтобы сообщить потоку для записи о том, что запись данных в него завершена, можно воспользоваться его методом ​end()​: writableStream.end()
    Этот метод принимает несколько необязательных параметров. В частности, ему можно передать последнюю порцию данных, которые надо записать в поток.
    Основы работы с MySQL в Node.js
    MySQL является одной из самых популярных СУБД в мире. В экосистеме Node.js имеется несколько пакетов, которые позволяют взаимодействовать с MySQL-базами, то есть — сохранять в них данные, получать данные из баз и выполнять другие операции.
    Мы будем использовать пакет ​
    mysqljs/mysql​
    . Этот проект, который существует уже очень давно, собрал более 12000 звёзд на GitHub. Для того чтобы воспроизвести следующие примеры, вам понадобится
    MySQL-сервер.

    Установка пакета
    Для установки этого пакета воспользуйтесь такой командой: npm install mysql
    Инициализация подключения к базе данных
    Сначала подключим пакет в программе: const mysql = require('mysql')
    После этого создадим соединение: const options = { user: 'the_mysql_user_name', password: 'the_mysql_user_password', database: 'the_mysql_database_name'
    } const connection = mysql.createConnection(options)
    Теперь попытаемся подключиться к базе данных: connection.connect(err => { if (err) { console.error('An error occurred while connecting to the DB') throw err
    }
    }
    Параметры соединения
    В вышеприведённом примере объект ​options​ содержал три параметра соединения: const options = { user: 'the_mysql_user_name', password: 'the_mysql_user_password', database: 'the_mysql_database_name'
    }
    На самом деле этих параметров существует гораздо больше. В том числе — следующие:
    ● host​ — имя хоста, на котором расположен MySQL-сервер, по умолчанию — ​localhost​.
    ● port​ — номер порта сервера, по умолчанию — ​3306​.
    ● socketPath​ — используется для указания сокета Unix вместо хоста и порта.
    ● debug​ — позволяет работать в режиме отладки, по умолчанию эта возможность отключена.
    ● trace​ — позволяет выводить сведения о трассировке стека при возникновении ошибок, по умолчанию эта возможность включена.

    ● ssl​ — используется для настройки SSL-подключения к серверу.
    Выполнение запроса SELECT
    Теперь всё готово к выполнению SQL-запросов к базе данных. Для выполнения запросов используется метод соединения ​query​, который принимает запрос и коллбэк. Если операция завершится успешно — коллбэк будет вызван с передачей ему данных, полученных из базы. В случае ошибки в коллбэк попадёт соответствующий объект ошибки. Вот как это выглядит при выполнении запроса на выборку данных: connection.query('SELECT * FROM todos', (error, todos, fields) => { if (error) { console.error('An error occurred while executing the query') throw error
    } console.log(todos)
    })
    При формировании запроса можно использовать значения, которые будут автоматически встроены в строку запроса: const id = 223 connection.query('SELECT * FROM todos WHERE id = ?', [id], (error, todos, fields) => { if (error) { console.error('An error occurred while executing the query') throw error
    } console.log(todos)
    })
    Для передачи в запрос нескольких значений можно, в качестве второго параметра, использовать массив: const id = 223 const author = 'Flavio' connection.query('SELECT * FROM todos WHERE id = ? AND author = ?', [id, author], (error, todos, fields) => { if (error) { console.error('An error occurred while executing the query') throw error

    } console.log(todos)
    })
    Выполнение запроса INSERT
    Запросы ​INSERT​ используются для записи данных в базу. Например, запишем в базу данных объект: const todo = { thing: 'Buy the milk' author: 'Flavio'
    } connection.query('INSERT INTO todos SET ?', todo, (error, results, fields) => { if (error) { console.error('An error occurred while executing the query') throw error
    }
    })
    Если у таблицы, в которую добавляются данные, есть первичный ключ со свойством ​auto_increment​, его значение будет возвращено в виде ​results.insertId​: const todo = { thing: 'Buy the milk' author: 'Flavio'
    } connection.query('INSERT INTO todos SET ?', todo, (error, results, fields) => { if (error) { console.error('An error occurred while executing the query') throw error
    }} const id = results.resultId console.log(id)
    )
    Закрытие соединения с базой данных
    После того как работа с базой данных завершена и пришло время закрыть соединение — воспользуйтесь его методом ​end()​:
    connection.end()
    Это приведёт к правильному завершению работы с базой данных.
    О разнице между средой разработки и продакшн-средой
    Создавая приложения в среде Node.js можно использовать различные конфигурации для окружения разработки и продакшн-окружения.
    По умолчанию платформа Node.js работает в окружении разработки. Для того чтобы указать ей на то, что код выполняется в продакшн-среде, можно настроить переменную окружения ​NODE_ENV​:
    NODE_ENV=production
    Обычно это делается в командной строке. В Linux, например, это выглядит так: export NODE_ENV=production
    Лучше, однако, поместить подобную команду в конфигурационный файл наподобие ​.bash_profile
    (при использовании Bash), так как в противном случае такие настройки не сохраняются после перезагрузки системы.
    Настроить значение переменной окружения можно, воспользовавшись следующей конструкцией при запуске приложения:
    NODE_ENV=production node app.js
    Эта переменная окружения широко используется во внешних библиотеках для Node.js.
    Установка ​NODE_ENV​ в значение ​production​ обычно означает следующее:
    ● До минимума сокращается логирование.
    ● Используется больше уровней кэширования для оптимизации производительности.
    Например, ​
    Pug​
    библиотека для работы с шаблонами, используемая Express, готовится к работе в режиме отладки в том случае, если переменная ​NODE_ENV​ не установлена в значение ​production​.
    Представления Express, в режиме разработки, генерируются при обработке каждого запроса. В продакшн-режиме они кэшируются. Есть и множество других подобных примеров.
    Express предоставляет конфигурационные хуки для каждого окружения. То, какой именно будет вызван, зависит от значения ​NODE_ENV​: app.configure('development', () => {
    //...
    }) app.configure('production', () => {
    //...
    }) app.configure('production', 'staging', () => {
    //...
    })

    Например, с их помощью можно использовать различные обработчики событий для разных режимов: app.configure('development', () => { app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
    }) app.configure('production', () => { app.use(express.errorHandler())
    })
    Надеемся, освоив это руководство, вы узнали о платформе Node.js достаточно много для того, чтобы приступить к работе с ней. Полагаем, теперь вы, даже если начали читать первую статью этого цикла, совершенно не разбираясь в Node.js, сможете начать писать что-то своё, с интересном читать чужой код и с толком пользоваться ​
    документацией​
    к Node.js.
    На всякий случай :)
    1   2   3   4   5   6   7   8   9


    написать администратору сайта