Для початку потрібно завантажити архів плагіна зі сторінки розробника та розпакувати його в директорію на вашому сайті. Доступні дві версії – мінімізована (Production version) та для розробників (Development version). У версії для розробників текст плагіна представлений у структурованому вигляді з коментарями, що зручно для того, щоб розібратися в принципі роботи (у вихідних матеріалах до уроку міститься версія плагіна для розробників з перекладеними коментарями).
Потім у секцію сторінки, на якій планується використовувати фільтрацію, потрібно вставити код підключення до плагіна:
$(document).ready(function() ( $("елемент_для_фільтрації").liveFilter("опція"); ));
Потрібно замінити “/шлях_до_плагіну/ ” на шлях, де розташований плагін liveFilter, який ви розпакували раніше. Також потрібно замінити "елемент_для_фільтрації" селектором CSS, який відповідає потрібному елементу.
Параметр плагіна "опція"керує використанням анімації при прихованні та виведенні елементів під час фільтрації. Доступні наступні значення: basic - елементи просто відключаються/включаються без будь-якої анімації, slide - елементи, що фільтруються, будуть згортатися/розвертатися, fade - елементи, що фільтруються, будуть поступово включатися/вимикатися.
Наприклад:
$(ul#filter_me").liveFilter("slide");
Вище наведений код вказує плагін LiveFilter фільтрувати неупорядкований список з id “ filter_me” та використовувати анімацію “ slide”.
Плагін можна використовувати для неупорядкованих та впорядкованих списків та таблиць. Потрібно вказати потрібний селектор під час виклику плагіна.
Важливо! Для роботи плагіна потрібно додати до сторінки поле введення тексту з класом "filter". Це поле буде використовуватися для введення тексту фільтрації:
Приклад сторінки з використанням фільтра:
Приклад використання плагіна LiveFilter $(document).ready(function() ( $(ul#filter_me").liveFilter("slide"); ));
- Пункт №1.
- Пункт №2.
- Пункт №3.
- Пункт №4.
- Пункт №5.
- Пункт №6.
- Пункт №7.
- Пункт №8.
- Пункт №9.
- Пункт №10.
(function($)( $.fn.liveFilter = function (aType) ( // Визначаємо, що буде фільтруватися. var filterTarget = $(this); var child; if ($(this).is("ul"))) ( child = "li"; ) else if ($(this).is("ol")) ( child = "li"; ) else if ($(this).is("table")) ( child = " tbody tr"; ) // Визначаємо змінні var hide; var show; var filter; // Подія для елемента введення $("input.filter").keyup(function() ( // Отримуємо значення фільтра filter = $(this) .val(); // Отримуємо те, що потрібно сховати, і те, що потрібно показати hide = $ (filterTarget). show = $(filterTarget).find(child + ":Contains("" + filter + "")") // Анімуємо пункти, які потрібно сховати і показати if (aType == "basic") ( hide.hide() ; else if (aType == "slide") ( hide.slideUp(500); show.slideDown(500); ) else if (aType == "fade") ( hide.fadeOut(400) );show.fadeIn(400); )); ).text().toLowerCase().indexOf(m.toLowerCase())>=0;
);
))) (jQuery);
nodejs stream (3)Я думаю, ви надто замислюєтеся, як усе це працює, і мені це подобається.
Які потоки хороші для
Потоки хороші для двох речей: коли операція повільна і вона може дати вам часткові результати в міру їх отримання. Наприклад, прочитайте файл, він повільний, тому що жорсткі диски повільні, і він може дати вам частину файлу в міру читання. З потоками можна використовувати ці частини файлу і відразу ж почати їх обробляти.вони також добре пов'язують програми разом (функція читання). Так само, як і в командному рядку, ви можете комбінувати
для отримання бажаного результату. приклад: cat file | grep word cat file | grep word.
Як вони працюють під капотом.Існують різні кодування, які може надсилати веб-сторінку. На початку був лише один спосіб. Коли вся сторінка була надіслана, коли її запросили. Тепер для цього є ефективніші кодування. Один із них фрагментується, коли частини веб-сторінки надсилаються до відправлення всієї сторінки. Це добре, тому що веб-сторінку може оброблятися в міру її отримання. Уявіть веб-браузер. Він може розпочати рендеринг веб-сайтів до завершення завантаження.
Ваші запитання та відповіді.По-перше, потоки Node.js працюють лише в одній програмі Node.js. Потоки Node.js не можуть взаємодіяти з потоком на іншому сервері або навіть у програмі.
Це означає, що наведений нижче приклад Node.js не може розмовляти з веб-сервером. Він не може сказати, щоб він зупинився чи відновився.
Node.js Network Webserver
Що дійсно відбувається, так це те, що Node.js запитує веб-сторінку, і він починає її завантажувати, і немає можливості зупинити це завантаження. Просто зніміть сокет.
Отже, що насправді відбувається, коли ви робите Node.js .pause або.continue?Він починає буферизувати запит, поки ви не будете готові знову його використовувати. Але завантаження ніколи не припинялося.
Event LoopУ мене є ціла відповідь, щоб пояснити, як працює Event Loop, але я думаю, що вам краще.
Перше, що слід зазначити: stream.js-потоки не обмежуються HTTP-запитами. HTTP-запити / Мережні ресурси - лише один приклад потоку в node.js.
Потоки корисні для всього, що можна обробляти невеликими шматками. Вони дозволяють обробляти потенційно величезні ресурси в невеликих шматках, які легше вписуються у вашу оперативну пам'ять.
Скажімо, у вас є файл (розміром кілька гігабайт) і ви хочете перетворити все малі літериу верхні регістри та записати результат в інший файл. Наївний підхід прочитав би весь файл, використовуючи fs.readFile (обробка помилок опущена для стислості):
fs. readFile ("my_huge_file", function (err, data) (var convertedData = data. toString(). toUpperCase(); fs. writeFile ("my_converted_file", convertedData);));На жаль, цей підхід буде легко перевантажувати вашу оперативну пам'ять, тому що весь файл має бути збережений перед його обробкою. Ви також витрачаєте дорогоцінний час на очікування на читання файлу. Чи не має сенсу обробляти файл у невеликих шматках? Ви можете почати обробку, як тільки ви отримаєте перші байти, чекаючи, поки жорсткий дискнадасть дані, що залишилися:
var readStream = fs. createReadStream ("my_huge_file"); var writeStream = fs. createWriteStream ("my_converted_file");readStream. on ( "data" , function (chunk ) ( var convertedChunk = chunk . toString (). toUpperCase (); writeStream . write (convertedChunk ); ));
Ви матимете справу лише з невеликими частинами даних, які легко впишуться у вашу оперативну пам'ять.
Ви починаєте обробляти, як тільки перший байт прибуває, і не витрачайте час на те, щоб нічого не робити, а чекати.
Тут також є актуальною перша проблема. Можливо, зловмисник відправляє вам великі обсяги даних, щоб перевантажити вашу RAM та видалити (DoS) вашу послугу.
Однак друга проблема ще важливіша в цьому випадку: мережа може бути дуже повільною (думаю, смартфони), і це може зайняти багато часу, доки все буде відправлено клієнтом. Використовуючи потік, можна розпочати обробку запиту і скоротити час відгуку. При зупинці потоку HTTP: це не виконується на рівні HTTP, але нижче. Якщо ви призупините поток, вузол node.js просто припинить читання з базового сокету TCP. Те, що відбувається тоді, залежить від ядра. Він все одно може буферизувати вхідні дані, тому він готовий для вас, як тільки ви закінчите свою поточну роботу. . Програмам не потрібно мати справу з цим. Це не їхня справа. Насправді програма відправника, ймовірно, навіть не розуміє, що ви більше не активно читаєте!Таким чином, це в основному надання даних, як тільки воно є, але без переважної кількості ресурсів. Основна складна робота виконується або
операційною системою
(наприклад, net , fs , http), або автором потоку (наприклад, zlib який є потоком Transform і зазвичай прикріплюється до fs або net).
Нижченаведена діаграма здається досить точним оглядом / діаграмою 10.000 футів для класу вузлових потоків. Останнє оновлення: 17.11.2018 Stream є потоком даних. Потоки бувають
різних типів
, серед яких можна виділити потоки для читання та потоки для запису .
Параметри request і response, які передаються в функцію і за допомогою яких ми можемо отримувати дані про запит і керувати відповіддю, якраз є потоками: request - потік для читання, а response - потік для запису.
Використовуючи потоки читання та запису, ми можемо зчитувати та записувати інформацію у файл. Наприклад:
Const fs = require ("fs"); let writeableStream = fs.createWriteStream("hello.txt"); writeableStream.write("Привіт світ!"); writeableStream.write("Продовження запису \n"); writeableStream.end("Завершення запису"); let readableStream = fs.createReadStream("hello.txt", "utf8"); readableStream.on("data", function(chunk)( console.log(chunk); ));
Для створення потоку для запису застосовується метод fs.createWriteStream() , який передається назву файла. Якщо раптом у папці немає такого файлу, він створюється.
Запис даних проводиться з допомогою методу write() , який передаються дані. Для закінчення запису викликається метод end().
Після цього у папці проекту з'являється файл hello.txt, який можна відкрити у будь-якому текстовому редакторі.
Для створення потоку для читання використовується метод fs.createReadStream() , який також передається назву файлу. Як опціональний параметр тут передається кодування, що дозволить відразу при читанні кодувати лічені дані в рядок у зазначеному кодуванні.
Сам потік розбивається на ряд шматків чи чанків (chunk). І при зчитуванні кожного такого шматка виникає подія data. За допомогою методу on() ми можемо підписатися на цю подію та вивести кожен шматок даних на консоль:
ReadableStream.on("data", function(chunk)( console.log(chunk); ));
Запустимо файл на виконання:
Тільки роботою з файлами функціональність потоків не обмежується, також є мережеві потоки, потоки шифрування, архівації тощо, але загальні принципироботи з ними будуть ті самі, що й у файлових потоків.
Нещодавно вийшла версія 10.5.0 платформи Node.js. Однією з її головних можливостей стала вперше додана в Node.js підтримка роботи з потоками, що поки що має статус експериментальної. Цей факт особливо цікавий у світлі того, що дана можливістьтепер є у платформи, адепти якої завжди пишалися тим, що потоки їй, завдяки фантастичній асинхронній підсистемі введення-виведення, не потрібні. Однак, підтримка потоків у Node.js все ж таки з'явилася. З чого б це? Кому і навіщо вони можуть стати в нагоді?
Якщо двома словами, то потрібно це для того, щоб платформа Node.js могла б досягти нових висот у тих областях, у яких раніше вона показувала не найчудовіші результати. Йдеться виконання обчислень, інтенсивно використовують ресурси процесора. Це в основному є причиною того, що Node.js не відрізняється сильними позиціямиу таких сферах, як штучний інтелект, машинне навчання, обробка великих обсягів даних. На те, щоб дозволити Node.js добре показати себе у вирішенні подібних завдань, спрямовано чимало зусиль, але тут ця платформа поки що виглядає скромніше, ніж, наприклад, у розробці мікросервісів.
Автор матеріалу, переклад якого ми сьогодні публікуємо, каже, що вирішив звести технічну документацію, яку можна знайти у вихідному пулл-запиті і в наборі простих практичних прикладів. Він сподівається, що будь-хто, хто розбере ці приклади, дізнається достатньо для того, щоб приступити до роботи з потоками в Node.js.
Зауважте, що працювати з worker_threads можна тільки використовуючи прапор -- experimental-worker при запуску скрипта, інакше система цей модуль не знайде.
Зверніть увагу на те, що прапор включає слово «worker» (воркер), а не «thread» (потік). Саме так, про що ми говоримо, згадується в документації, в якій використовуються терміни «worker thread» (потік воркера) або просто «worker» (воркер). Надалі і ми дотримуватимемося такого ж підходу.
Про завдання, які можна вирішувати за допомогою воркерів в Node.js Потоки воркерів призначені, як уже було сказано, для вирішення завдань, які інтенсивно використовують можливості процесора. Слід зазначити, що застосування їх для вирішення завдань введення-виведення - це марна витрата ресурсів, оскільки, відповідно до офіційної документації, внутрішні механізми Node.js, спрямовані на організацію асинхронного введення-виведення, самі по собі набагато ефективніші, ніж використання для вирішення тієї ж задачі потоків воркерів. Тому відразу вирішимо, що введенням-виведенням даних за допомогою воркерів ми не займатимемося.Почнемо з простого прикладу, який демонструє порядок створення та використання воркерів.
Приклад № 1 const (Worker, isMainThread, workerData) = require("worker_threads"); let currentVal = 0; let intervals = функція counter(id, i)( console.log("[", id, "]", i) return i; ) if(isMainThread) ( console.log("this is the main thread") for( let i = 0;< 2; i++) { let w = new Worker(__filename, {workerData: i}); } setInterval((a) =>currentVal = counter(a,currentVal + 1), intervals, "MainThread"); ) else ( console.log("this isn"t") setInterval((a) => currentVal = counter(a,currentVal + 1), intervals, workerData); )Висновок цього коду буде виглядати як набір рядків, що демонструють лічильники, значення яких збільшуються з різною швидкістю.
Результати роботи першого прикладу
Розберемося з тим, що відбувається:
Const (Worker, isMainThread, parentPort, workerData) = require("worker_threads"); const request = require ("request"); if(isMainThread) ( console.log("This is the main thread") w = new Worker(__filename, (workerData: null))), w.on("message", (msg) => ( //Повідомлення від воркера! console.log("First value is: ", msg.val); console.error); w.on("exit", (code) => ( if(code != 0) console.error(new Error(`Worker stopped with exit code $(code)`)))) .get("http://www.google.com", (err, resp) => ( if(err) ( return console.error(err); ) console.log("Total bytes received: ", resp. body.length); )) ) else ( //код воркера function random(min, max) ( return Math.random() * (max - min) + min ) const sorter = require("./list-sorter") ; const start = Date.now() let bigList = Array(1000000).fill().map((_) => random(1,10000)) sorter.sort(bigList); .firstValue, timeDiff: Date.now() - start));
Для того, щоб запустити в себе цей приклад, зверніть увагу на те, що цьому коду потрібен модуль request (його можна встановити за допомогою npm, наприклад, скориставшись у порожній директорії з файлом, що містить вищенаведений код, командами npm init --yes і npm install request --save), і те, що він використовує допоміжний модуль, що підключається командою const sorter = require("./list-sorter"); . Файл цього модуля (list-sorter.js) повинен бути там же, де і вищеописаний файл, його код виглядає так:
Module.exports = ( firstValue: null, sort: function(list) ( let sorted = list.sort(); this.firstValue = sorted ) )
На цей раз ми паралельно вирішуємо два завдання. По-перше – завантажуємо домашню сторінку google.com, по-друге – сортуємо випадково згенерований масив із мільйона чисел. Це може зайняти кілька секунд, що дає нам чудову нагоду побачити нові механізми Node.js у справі. Крім того, тут ми вимірюємо час, який потрібен потоку воркера для сортування чисел, після чого відправляємо результат вимірювання (разом з першим елементом відсортованого масиву) головному потоку, який виводить результати в консоль.
Результат роботи другого прикладу
У цьому прикладі найголовніше – це демонстрація механізму обміну даними між потоками.
Воркери можуть отримувати повідомлення з головного потоку завдяки методу on. У коді можна знайти події, які ми слухаємо. Подія message викликається кожного разу, коли ми відправляємо повідомлення з потоку з використанням методу parentPort.postMessage . Крім того, той же метод можна використовувати для надсилання повідомлення потоку, звертаючись до екземпляра воркера, і отримувати їх за допомогою об'єкта parentPort .
Тепер розглянемо ще один приклад, дуже схожий на те, що ми вже бачили, але цього разу приділимо особливу увагуструктуру проекту.
Приклад №3 Як останній приклад пропонуємо розглянути реалізацію того ж функціонала, що і в попередньому прикладі, але цього разу покращимо структуру коду, зробимо його чистішим, приведемо його до вигляду, який підвищує зручність підтримки програмного проекту.Ось код основної програми.
Const (Worker, isMainThread, parentPort, workerData) = require("worker_threads"); const request = require ("request"); function startWorker(path, cb) (let w = новий Worker(path, (workerData: null))); error", cb); return w; ) console.log("this is the main thread") let myWorker = startWorker(__dirname + "/workerCode.js", (err, result) => ( if(err) return console.error(err); console.log("[]") console.log("First value is: ", result.val); console.log("Took: ", (result.timeDiff / 1000), " seconds")); start = Date.now(); request.get("http://www.google.com", (err, resp) => ( if(err) ( return console.error(err); ) console.log("Total bytes received: ", resp .body.length); //myWorker.postMessage((finished: true, timeDiff: Date.now() - start)) //так можна відправляти повідомлення воркеру ))
А ось код, що описує поведінку потоку воркера (у наведеній вище програмі шлях до файлу з цим кодом формується за допомогою конструкції __dirname + "/workerCode.js"):
Const (parentPort) = require("worker_threads"); function random(min, max) ( return Math.random() * (max - min) + min ) const sorter = require("./list-sorter"); const start = Date.now() let bigList = Array(1000000).fill().map((_) => random(1,10000)) /** //ось як отримати повідомлення з головного потоку: parentPort.on ( "message", (msg) => ( console.log("Main thread finished on: ", (msg.timeDiff / 1000), " seconds..."); )) */ sorter.sort(bigList); parentPort.postMessage(( val: sorter.firstValue, timeDiff: Date.now() - start));
Ось особливості цього прикладу:
Шановні читачі!