Хочете краще зрозуміти буфер в Node.js? Перевір це.

Ви завжди дивувало, як і я, щоразу , коли ви зустрічаєте слова , як буфер, потік, і виконавчі дані вNode.js? Чи змушує вас це почуття ухилятися від їх розуміння, думаючи, що вони призначені не для вас, а лише для розуміння гуру та розробників пакетів Node.js?

Дійсно, ці слова можуть бути дуже лякаючими, особливо коли ви починаєте розробку веб-сайтів за допомогою Node.js без будь-яких ступенів CS.

На жаль, багато навчальних посібників та книг перейдуть безпосередньо до навчання, як розробляти веб-додатки за допомогою пакетів Node.js, не даючи вам зрозуміти основні особливості Node.js та чому вони існують. А деякі нахабно скажуть вам, що вам не потрібно їх розуміти, бо виможе ніколи не працювати з ними безпосередньо.

Ну, правда, ви ніколи не зможете працювати з ними безпосередньо, якщо вирішите залишатися пересічним розробником Node.js.

Однак, якщо таємниці викликають у вас справді цікавість, і ви ні перед чим не зупинитесь, щоб задовольнити свою цікавість, і якщо ви хочете підняти своє розуміння Node.js на наступний рівень, то ви дійсно хочете копати глибше, щоб зрозуміти багато основних функцій Node.js, як, наприклад, Buffer . І саме тому я пишу цей твір - щоб допомогти нам демістифікувати деякі з цих функцій і підняти наше навчання Node.js на новий рівень.

При введенні буфера офіційні документи Node.js частково стверджують ...

… Механізм зчитування або маніпулювання потоками двійкових даних. BufferКлас був введений як частина API Node.js , щоб зробити можливим взаємодіяти з октет потоків в контексті таких речей , як TCP потоки і операції з файловою системою.

Хммм, якщо ви не знали попередньо всіх слів у вищезазначених реченнях, це, мабуть, лише купа жаргонів. Спробуємо трохи спростити це, переформулювавши його, щоб ми могли мати чіткий фокус і не відволікатися на численні навороти. Витягуючи з цього вступу, ми могли б сміливо сказати:

BufferКлас був введений як частина API Node.js , щоб зробити можливим , щоб маніпулювати або взаємодіяти з потоками двійкових даних.

Тепер це простіше, чи не так? Але ... Буфер, потоки, двійкові дані ... все ще багато важливих слів. Ну, спробуємо вирішити ці великі слова від останнього до першого.

Двійкові дані, що це?

Напевно, ви вже знаєте, що комп’ютери зберігають і представляють дані у двійкових файлах. Бінарний файл - це просто набір або колекція 1 і 0. Наприклад, нижче подано п’ять різних двійкових файлів, п’ять різних наборів 1 і 0:

10, 01, 001, 1110,00101011

Кожне число в двійковій, кожен 1і 0в наборі називається біт , який є короткою формою двійковій цифри.

Щоб зберігати або представляти шматок даних, комп’ютер повинен перетворити ці дані в двійкове представлення. Наприклад, щоб зберегти число 12, комп'ютер повинен перетворити 12 у його двійкове представлення, яке є 1100.

Звідки комп’ютер знає, як зробити це перетворення? Ну, це чиста математика. Це проста система двійкових чисел, яку ми вивчили з базової математики - виражаючи число в системі числення основи-2. Комп’ютери розуміють цю математику.

Але цифри - не єдиний тип даних, з яким ми працюємо. У нас також є струни, зображення та навіть відео. Комп’ютери знають, як представляти всі типи даних у двійкових файлах. Візьмемо, наприклад, струни. Як комп'ютер буде представляти рядок "L" у двійкових файлах? Щоб зберегти будь-який символ у двійкових файлах, Комп’ютери спочатку перетворять цей символ у число, а потім перетворять це число у його двійкове представлення. Отже, для рядка "L",комп'ютери першого перетворення L на номер , який являє собою L . Подивимось як.

Відкрийте консоль браузера і вставте наступний фрагмент коду , а потім натисніть Enter: "L".charCodeAt(0). Що ви бачили? Число 76? Тобто число уявлення або код символу або Code Point ієрогліфа L . Але звідки комп’ютер знає, яке саме число буде представляти кожен символ? Звідки воно знає, як використовувати число 76 для представлення L ?

Набори символів

Набори символів - це вже визначені правила того, яке саме число представляє кожен символ. У нас є різні визначення цих правил. До найпопулярніших належать Unicode та ASCII . JavaScript дуже добре працює з наборами символів Unicode. Насправді, це Unicode в вашому браузері , який свідчить , що 76 повинні представляти L .

Отже, ми бачили, як комп’ютери представляють символи в цифрах. Тепер комп’ютер, у свою чергу, представлятиме число 76 у своєму двійковому поданні. Можна подумати, ну, просто перетворіть 76 у систему числення основи-2. Не так швидко!

Кодування символів

Подібно до того, як існують правила, що визначають, яке число повинно представляти символ, існують також правила, що визначають, як це число повинно бути представлене у двійкових файлах. Зокрема, скільки бітів використовувати для представлення числа. Це називається кодуванням символів .

Одним із визначень кодування символів є UTF-8 . UTF-8 зазначає, що символи повинні кодуватися в байтах. Байт - це набір з восьми бітів - восьми 1 і 0. Отже, вісім 1 і 0 повинні використовуватися для представлення кодової точки будь-якого символу в двійковому вигляді.

Щоб зрозуміти це, як ми вже згадували раніше, двійкове представлення числа 12 є 1100. Отже, коли UTF-8 стверджує, що 12 має бути у восьми бітах, UTF-8 говорить, що комп’ютеру потрібно додати більше бітів до лівої сторони фактичного представлення base-2 числа 12, щоб зробити його байтом. Тож 12 слід зберігати як 00001100. Має сенс?

Тому 76 слід зберігати як 01001100.

Це, друзі, так комп'ютери зберігають рядки або символи у двійкових файлах. Подібним чином, комп’ютери також мають визначені правила щодо того, як зображення та відео слід перетворювати або кодувати та зберігати у двійкових файлах. Справа в тому, що комп’ютери зберігають усі типи даних у двійкових файлах, і це відоме як двійкові дані.

Якщо вас надзвичайно цікавить крихітне кодування символів, вам може сподобатися цей ніжний та детальний вступ.

Тепер ми розуміємо, що таке двійкові дані, але що таке потоки двійкових данихвід нашого вступу до буфера?

Потік

Потік у Node.js просто означає послідовність даних, яка з часом переміщується з однієї точки в іншу. Вся концепція полягає в тому, що у вас є величезна кількість даних для обробки, але вам не потрібно чекати, поки всі дані стануть доступними, перш ніж почати їх обробляти.

В основному ці великі дані розбиваються і надсилаються шматками. Отже, з початкового визначення буфера («потоки двійкових даних ... у контексті ... файлової системи») це просто означає, що двійкові дані переміщуються у файловій системі. Наприклад, переміщення текстів, що зберігаються у файлі file1.txt, у файл file2.txt.

Але як саме буфер допомагає нам взаємодіяти або маніпулювати бінарними даними під час потокової передачі? Що саме являє собою цей буфер до речі?

Буфер

Ми бачили, що потік даних - це переміщення даних від однієї точки до іншої, але як саме вони переміщуються?

Як правило, переміщення даних відбувається, як правило, з метою їх обробки або читання та прийняття рішень на їх основі. Але існує мінімальний і максимальний обсяг даних, який процес може зайняти з часом. Отже, якщо швидкість надходження даних швидша, ніж швидкість, яку процес споживає дані, надлишкові дані потрібно десь зачекати, поки їх черга буде оброблена.

З іншого боку, якщо процес споживає дані швидше, ніж надходить, тим небагатьом даним, які надходять раніше, потрібно почекати, поки надійде певний обсяг даних, перш ніж відправити їх на обробку.

Ця “зона очікування - це буфер! Це невелике фізичне місце у вашому комп’ютері, як правило, в оперативній пам’яті, де дані тимчасово збираються, чекають і в кінцевому підсумку відправляються на обробку під час потокового передавання.

Ми можемо уявити весь процес потоку та буферу як автовокзал. На деяких автостанціях автобус не має права відправлятися доти, поки не прибуде певна кількість пасажирів або до певного часу відправлення. Також пасажири можуть прибувати в різний час з різною швидкістю. Ні пасажири, ні автовокзал не контролюють прибуття пасажирів на вокзал.

У будь-якому випадку пасажирам, які прибувають раніше, потрібно буде почекати, поки автовокзал вирішить відправити автобус у дорогу. У той час як пасажирам, які прибувають, коли автобус вже завантажується або коли автобус уже відправляється, потрібно почекати наступний автобус.

Як би там не було, завжди є місце очікування. Це буфер для Node.js! Node.js не може контролювати швидкість або час надходження даних, швидкість потоку. Він може лише вирішити, коли пора надсилати дані. Якщо ще не час, Node.js помістить їх у буфер - "область очікування" - невелике місце в оперативній пам'яті, поки не настане час відправити їх на обробку.

Типовим прикладом, коли ви можете бачити буфер в дії, є потокове передавання відео в Інтернеті. Якщо ваше підключення до Інтернету досить швидке, швидкість потоку буде достатньо швидкою, щоб миттєво заповнити буфер і відправити його на обробку, потім заповнити ще один, і відправити його, потім ще один, і ще один ... до потоку закінчено.

Але якщо ваше з’єднання повільне, після обробки першого набору даних, що надійшов, відеоплеєр відобразить піктограму завантаження або відобразить текст “буферизація”, що означає збір більшої кількості даних або очікування отримання більше даних. І коли буфер заповнюється та обробляється, програвач показує дані, відео. Під час відтворення більше даних буде продовжувати надходити і чекати в буфері.

Якщо програвач закінчив обробку або відтворення попередніх даних, а буфер ще не заповнений, текст "буферизація" знову відобразиться, чекаючи збору додаткових даних для обробки.

Це буфер!

З оригінального визначення буфера видно, що перебуваючи в буфері, ми можемо маніпулювати або взаємодіяти з двійковими даними, які передаються в потоці. Яку взаємодію ми могли б мати з цими вихідними двійковими даними? Реалізація буфера в Node.js надає нам цілий список того, що можна здійснити. Подивимось деякі з них.

Взаємодія з буфером

Можна навіть створити власний буфер! Окрім того, що Node.js автоматично створюватиметься під час потоку, можна створити і управляти власним буфером. Цікаво, правда? Давайте створимо його!

Залежно від того, чого ви хочете досягти, існують різні способи створення буфера. Давайте подивимось деякі.

// Create an empty buffer of size 10. // A buffer that only can accommodate 10 bytes.
const buf1 = Buffer.alloc(10);
// Create a buffer with content
const buf2 = Buffer.from("hello buffer");

Після створення вашого буфера ви можете почати з ним взаємодіяти

// Examine the structure of a buffer
buf1.toJSON()// { type: 'Buffer', data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }// an empty buffer
buf2.toJSON()// { type: 'Buffer', data: [ 104, 101, 108, 108, 111, 32, 98, 117, 102, 102, 101, 114 ] }
// the toJSON() method presents the data as the Unicode Code Points of the characters
// Examine the size of a buffer
buf1.length // 10
buf2.length // 12. Auto-assigned based on the initial content when created.
// Write to a bufferbuf1.write("Buffer really rocks!") 
// Decode a buffer
buf1.toString() // 'Buffer rea'
//oops, because buf1 is created to contain only 10 bytes, it couldn't accommodate the rest of the characters
// Compare two buffers

Ми можемо мати багато взаємодій з буфером. Перейдіть до офіційних документів, щоб більше пограти з цими методами.

Нарешті, я залишу вам цей невеликий виклик: прочитайте джерело zlib.js , одну з основних бібліотек Node.js, щоб побачити, як це використовує потужність буфера для маніпулювання потоками двійкових даних. Це виявляються файли у стилі gziped. Читаючи, документуйте те, що дізнаєтесь, і люб’язно діліться з нами тут у коментарях.

Сподіваюся, цей вступ допоміг вам краще зрозуміти буфер Node.js.

Якщо ви відчуваєте, що я зробив гарну роботу, і що інші заслуговують на можливість побачити це, ласкаво поплескайте за статтю, щоб допомогти поширити краще розуміння буфера в нашій спільноті Node.js.

Якщо у вас є запитання, на яке не отримали відповіді, або ви по-іншому розумієте деякі пункти тут, сміливо пишіть коментарі тут або через Twitter.