SlideShare a Scribd company logo
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
Node.js in 2020 #1
Выйди и зайди нормально
Timur Shemsedinov
github.com/HowProgrammingWorks
github.com/tshemsedinov
Chief Technology Architect at Metarhia
Lecturer at Kiev Polytechnic Institute
github.com/tshemsedinov
https://youtube.com/TimurShemsedinov
github.com/HowProgrammingWorks/Index
Весь курс по ноде (>35.5 часов)
https://habr.com/ru/post/485294/
t.me/HowProgrammingWorks
t.me/NodeUA
timur.shemsedinov@gmail.com
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
Node.js Starter Kit
no dependencies: 15kb size,
with PG drivers + 1.2mb
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Starter Kit Key Ideas
● Минимум кода и зависимостей
● Минимизация I/O, отдача всего из памяти
● Безопасность и изоляция контекстов
● Структура и архитектура приложения
● Разделение системного и прикладного слоя
● Все на контрактах (interface)
● Балансировка, таймауты и очередь запросов
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Starter Kit Feature List
● Автороутинг API и поддержка HTTP(S), WS(S)
● Подгрузка изменений на лету через fs.watch
● Загрузчик конфигурации и Graceful shutdown
● Утилизация CPU, кластеризация через потоки
● Слой доступа к данным DAL: Postgresql
● Сессии с сохраняемым состоянием
● Песочницы, потоки, масштабирование, тесты
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
Node.js in 2020
State of the platform
and future
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Node.js уже 10 лет: v0.0.1 — 27 мая 2019
0.10.x и 0.12.x — (2013 - 2016)
Io.js 1.x, 2.x, 3.x — (2014 - 2015)
Argon 4.x (2015 - 2018), 5.x (2015 - 2016),
Boron 6.x (2016 - 2019), 7.x (2016 - 2017),
Carbon 8.x (2017 - 2019), 9.x (2017 - 2018),
Dubnium 10.x (2018 - 2021),11.x (2018 - 2019),
Erbium 12.x (2019 - 2022), 13.x (to June 2020)
14.x (April 2020 - April 2023), 15.x(2020-)
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Node.js features
8.x V8 6.0, async/await, TurboFan and Ignition
10.x V8 6.6, HTTP/2, fs.promises, BigInt, npm 6
12.x V8 7.8, TLS 1.3, OpenSSL 1.1.1c, npm 6.10.3
js: #, static, async/await, async stack,
динамическая куча, llhttp и llparser,
threads, DOS в HTTP/2, startup,
fs.rmdir & fs.Dir, process.resourceUsage()
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Node.js features
13.x V8 7.8, npm 6.13.6, libuv 1.34.1
WASI, worker.resourceLimits, vm.Module
Source map, Advanced Serialization API
14.x Ожидания: V8 8.x: больше доступа к v8 api
HTTP/3 (HTTP over IETF QUIC)
улучшения в WASI, N-API, async_hooks
streams, в работе с workers и esm
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Shared memory and Atomics
Появилось в Node.js 9
■ SharedArrayBuffer
■ Atomics
○ add, sub, and, or, xor
○ store, load, exchange, compareExchange
○ notify, wait, wake (deprecated)
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Threads vs Processes
process process
JavaScript
thread
V8libuv
node.js
JavaScript
thread
V8 libuv
node.js
JavaScript
thread
V8 libuv
node.js
IPC
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Why Isolation?
● Ошибки
● Утечки памяти и других ресурсов
● Приложение: данные, соединения с БД
● Файловая система и корневой каталог
● Окружение ОС, PID, IPC
● Безопасность ОС: пользователи, группы
● Сеть: дескрипторы сокетов, порты, хосты
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Execution Strategy Problems
● Недостаточная изоляция исполнения
запросов к серверу друг от друга
● Один неудачный запрос может убить все
параллельно исполняемые
● В асинхронной среде сложно найти и
связать ошибку с запросом
● Изоляция приложений и организаций в SaaS
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Execution Isolation
● VPS (виртуальная машина)
● Контейнер (Docker)
● Провесс (node)
● Поток (встроенный модуль worker_threads)
● Песочница (vm.createContext, vm.Script)
● Программная абстракция
(объект или замыкание)
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Links
Node https://nodejs.org/en/about/releases/
https://nodejs.org/en/blog/
https://node.green/
Deno https://github.com/denoland/deno
https://youtu.be/z6JRlx5NC9E
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Deno
● Безопасность:
файловая система, сеть, окружение
● V8, TypeScript
● Rust вместо C++
● Tokio (event loop, I/O scheduler)
● Встроенный менеджер пакетов
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Node.js
Готовность ноды для серьезных систем
Проблемы ноды
● Безопасность, заражения, зависимости
● Потерянные ошибки, утечки, перезапуски
● Асинхронность и стектрейс
Перспективы платформы
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
v8 Serialization API
v8.serialize, v8.deserialize
v8.Serializer, v8.Deserializer
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Race Condition
const v8 = require('v8');
const dataset = [
{ name: 'Marcus Aurelius', born: 121 },
{ name: 'Mao Zedong', born: 1893 },
];
const v8Data = v8.serialize(dataset);
const obj = v8.deserialize(v8Data);
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
v8 Serialization
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
vm Sandboxing
vm.Script, vm.runInContext
and v8::Context
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
vm.createContext
const vm = require('vm');
const sandbox = {
console: new Logger(),
require: wrap(require),
application: new Application(),
};
sandbox.global = sandbox;
vm.createContext(sandbox);
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
vm.Script
const vm = require('vm');
const fs = require('fs');
const code = await fs.readFile(fileName, 'utf8');
const src = `'use strict';n context => ${code}`;
const script = new vm.Script(src);
script.runInContext(sandbox, { timeout: 5000 });
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
vm.Script
const options = {
timeout: 5000,
displayErrors: false, // default: true
breakOnSigint: true, // default: false, CTRL+C
};
script.runInContext(sandbox, options);
const object = { /* global */ };
script.runInNewContext(object, options);
script.runInThisContext(options);
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
ES.Next
ECMAScript 2020
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
ES.Next features
● Приватные и статические поля
● Изменения в Array, Object, String
● Atomics и SheredArrayBuffer
● Коллекции Set, Map, WeakSet, WeakMap
● globalThis
● Math
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Operators
Rest
const f = (a, b, ...array) => {};
const g = ({ a, b, ...array }) => {};
const { name, ...rest } = obj;
Spread
f(a, b, ...array);
const obj2 = { name, ...obj1 };
const clone = { ...obj };
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Operators
Exponentiation
Math.pow(x, y) x ** y x **= y x = x ** y
Optional chaining
const spqr = {
emperor: { name: 'Marcus' }
};
console.log(spqr.emperor?.name);
console.log(spqr.president?.name);
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Operators
Exponentiation
Math.pow(x, y) x ** y x **= y x = x ** y
Optional chaining (still waiting v8 8.x in Node.js)
const spqr = {
emperor: { name: 'Marcus' }
};
console.log(spqr.emperor?.name);
console.log(spqr.president?.name);
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Asynchronous iterable contract
Symbol.iterator
iterable[Symbol.iterator]()
Symbol.asyncIterator
asyncIterable[Symbol.asyncIterator]()
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Try...catch
try {
throw new Error('message');
} catch {
console.log('no arguments catched');
}
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Function
((a, b) => {
const c = a + b; // hello there
return c;
}).toString()
"(a, b) => {
const c = a + b; // hello there
return c;
}"
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Promise.finally
new Promise(executor)
.then(onFulfilled[, onRejected])
.catch(onRejected)
.finally(onFinally);
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Promise.allSettled
const p1 = Promise.resolve('p1');
const p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'p2');
});
const p3 = new Promise((resolve, reject) => {
setTimeout(reject, 100, 'p3');
});
Promise.all([p1, p2, p3]).then(values => {
console.log(values);
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Promise.allSettled
Promise.all([p1, p2, p3]).then(values => {
console.log(values);
});
node:26549) UnhandledPromiseRejectionWarning: p3
(node:26549) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. This error originated either by throwing inside of an
async function without a catch block, or by rejecting a promise
which was not handled with .catch(). (rejection id: 1)
(node:26549) [DEP0018] DeprecationWarning: Unhandled promise
rejections are deprecated. In the future, promise rejections that
are not handled will terminate the Node.js process with
a non-zero exit code.
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Promise.allSettled
const p1 = Promise.resolve('p1');
const p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'p2');
});
const p3 = new Promise((resolve, reject) => {
setTimeout(reject, 100, 'p3');
});
Promise.allSettled([p1, p2, p3]).then(values => {
console.log(values);
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Promise.allSettled
Promise.allSettled([p1, p2, p3]).then(values => {
console.log(values);
});
[
{ status: 'fulfilled', value: 'p1' },
{ status: 'fulfilled', value: 'p2' },
{ status: 'rejected', reason: 'p3' }
]
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
Состояние гонки
В параллельном и
асинхронном
программировании
Web Locks API
in node.js & browser
Timur Shemsedinov
Chief Technology Architect at Metarhia
Lecturer at KPI
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Why do we need Web Locks API ?
— Do you know what is
mutex, locks, critical section, race condition,
parallel programming at all?
— Congrats!
It’s is very likely that
all your JavaScript code broken )))
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Concurrent Computing
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Concurrency Problems
● Race condition
● Deadlock
● Livelock
● Resource starvation
● Resource leaks
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Synchronization Primitives
Semaphore
Binary semaphore
Counting semaphore
Condition variable
Spinlock
Mutex
Timed mutex
Shared mutex
Recursive mutex
Monitor
Barrier
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Links
Spec: wicg.github.io/web-locks
MDN: developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API
Implementation: github.com/metarhia/web-locks
Examples:
github.com/HowProgrammingWorks/RaceCondition
github.com/HowProgrammingWorks/Semaphore
github.com/HowProgrammingWorks/Mutex
Async prog: habr.com/ru/post/452974/
Questions?
github.com/tshemsedinov
https://youtube.com/TimurShemsedinov
github.com/HowProgrammingWorks/Index
Весь курс по ноде (>35.5 часов)
https://habr.com/ru/post/485294/
t.me/HowProgrammingWorks
t.me/NodeUA
timur.shemsedinov@gmail.com

More Related Content

What's hot (20)

PDF
Programming Languages: comparison, history, future
Timur Shemsedinov
 
PDF
Node.js in 2020 - part 2
Timur Shemsedinov
 
PDF
Private cloud without vendor lock // Serverless
Timur Shemsedinov
 
PDF
Введение в SQL
Timur Shemsedinov
 
PDF
How to keep control and safety in the clouds
Timur Shemsedinov
 
PDF
JavaScript в браузере: Web API (часть 1)
Timur Shemsedinov
 
PDF
Prototype programming in JavaScript
Timur Shemsedinov
 
PDF
Asynchronous programming and mutlithreading
Timur Shemsedinov
 
PDF
Node.js middleware: Never again!
Timur Shemsedinov
 
PDF
Asynchronous programming with java script and node.js
Timur Shemsedinov
 
PDF
Metarhia KievJS 22-Feb-2018
Timur Shemsedinov
 
PDF
JS Fest 2019 Node.js Antipatterns
Timur Shemsedinov
 
PDF
JavaScript - Agora nervoso
Luis Vendrame
 
PDF
Duralexsedregex
Wairton Abreu
 
PDF
Bytes in the Machine: Inside the CPython interpreter
akaptur
 
PDF
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
akaptur
 
PPTX
Building HTML5 enabled web applications with Visual Studio 2011
Microsoft Developer Network (MSDN) - Belgium and Luxembourg
 
PDF
What they don't tell you about JavaScript
Raphael Cruzeiro
 
PDF
Python sqlite3
Alexey Bovanenko
 
Programming Languages: comparison, history, future
Timur Shemsedinov
 
Node.js in 2020 - part 2
Timur Shemsedinov
 
Private cloud without vendor lock // Serverless
Timur Shemsedinov
 
Введение в SQL
Timur Shemsedinov
 
How to keep control and safety in the clouds
Timur Shemsedinov
 
JavaScript в браузере: Web API (часть 1)
Timur Shemsedinov
 
Prototype programming in JavaScript
Timur Shemsedinov
 
Asynchronous programming and mutlithreading
Timur Shemsedinov
 
Node.js middleware: Never again!
Timur Shemsedinov
 
Asynchronous programming with java script and node.js
Timur Shemsedinov
 
Metarhia KievJS 22-Feb-2018
Timur Shemsedinov
 
JS Fest 2019 Node.js Antipatterns
Timur Shemsedinov
 
JavaScript - Agora nervoso
Luis Vendrame
 
Duralexsedregex
Wairton Abreu
 
Bytes in the Machine: Inside the CPython interpreter
akaptur
 
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
akaptur
 
Building HTML5 enabled web applications with Visual Studio 2011
Microsoft Developer Network (MSDN) - Belgium and Luxembourg
 
What they don't tell you about JavaScript
Raphael Cruzeiro
 
Python sqlite3
Alexey Bovanenko
 

Similar to Node.js in 2020 - part 1 (19)

PPTX
Oh Composable World!
Brian Lonsdorf
 
PDF
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
PDF
Everything is composable
Victor Igor
 
PPTX
Seminar PSU 10.10.2014 mme
Vyacheslav Arbuzov
 
PDF
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
ConFoo
 
PDF
Transducers in JavaScript
Pavel Forkert
 
PDF
Internal workshop es6_2015
Miguel Ruiz Rodriguez
 
PDF
Pune Clojure Course Outline
Baishampayan Ghose
 
PDF
Spark workshop
Wojciech Pituła
 
PDF
Reactive programming with RxJS - ByteConf 2018
Tracy Lee
 
PDF
Christian Gill ''Functional programming for the people''
OdessaJS Conf
 
PPTX
Python queue solution with asyncio and kafka
Ondřej Veselý
 
PDF
PostgreSQL 9.6 새 기능 소개
PgDay.Seoul
 
PDF
ClojureScript loves React, DomCode May 26 2015
Michiel Borkent
 
PDF
Scala collections
Inphina Technologies
 
PDF
Scala Collections
Meetu Maltiar
 
PPTX
Es6 hackathon
Justin Alexander
 
PDF
Python Cheat Sheet
Muthu Vinayagam
 
PPTX
Java
박 경민
 
Oh Composable World!
Brian Lonsdorf
 
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
Everything is composable
Victor Igor
 
Seminar PSU 10.10.2014 mme
Vyacheslav Arbuzov
 
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
ConFoo
 
Transducers in JavaScript
Pavel Forkert
 
Internal workshop es6_2015
Miguel Ruiz Rodriguez
 
Pune Clojure Course Outline
Baishampayan Ghose
 
Spark workshop
Wojciech Pituła
 
Reactive programming with RxJS - ByteConf 2018
Tracy Lee
 
Christian Gill ''Functional programming for the people''
OdessaJS Conf
 
Python queue solution with asyncio and kafka
Ondřej Veselý
 
PostgreSQL 9.6 새 기능 소개
PgDay.Seoul
 
ClojureScript loves React, DomCode May 26 2015
Michiel Borkent
 
Scala collections
Inphina Technologies
 
Scala Collections
Meetu Maltiar
 
Es6 hackathon
Justin Alexander
 
Python Cheat Sheet
Muthu Vinayagam
 
Ad

More from Timur Shemsedinov (15)

PDF
How to use Chat GPT in JavaScript optimizations for Node.js
Timur Shemsedinov
 
PDF
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
Timur Shemsedinov
 
PDF
Multithreading in Node.js and JavaScript
Timur Shemsedinov
 
PDF
Node.js threads for I/O-bound tasks
Timur Shemsedinov
 
PDF
Node.js Меньше сложности, больше надежности Holy.js 2021
Timur Shemsedinov
 
PDF
Rethinking low-code
Timur Shemsedinov
 
PDF
Hat full of developers
Timur Shemsedinov
 
PDF
FwDays 2021: Metarhia Technology Stack for Node.js
Timur Shemsedinov
 
PDF
Node.js for enterprise - JS Conference
Timur Shemsedinov
 
PDF
Node.js for enterprise 2021 - JavaScript Fwdays 3
Timur Shemsedinov
 
PDF
Node.js in 2021
Timur Shemsedinov
 
PDF
Information system structure and architecture
Timur Shemsedinov
 
PDF
Базы данных в 2020
Timur Shemsedinov
 
PDF
Почему хорошее ИТ-образование невостребовано рыночком
Timur Shemsedinov
 
PDF
Node.js security
Timur Shemsedinov
 
How to use Chat GPT in JavaScript optimizations for Node.js
Timur Shemsedinov
 
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
Timur Shemsedinov
 
Multithreading in Node.js and JavaScript
Timur Shemsedinov
 
Node.js threads for I/O-bound tasks
Timur Shemsedinov
 
Node.js Меньше сложности, больше надежности Holy.js 2021
Timur Shemsedinov
 
Rethinking low-code
Timur Shemsedinov
 
Hat full of developers
Timur Shemsedinov
 
FwDays 2021: Metarhia Technology Stack for Node.js
Timur Shemsedinov
 
Node.js for enterprise - JS Conference
Timur Shemsedinov
 
Node.js for enterprise 2021 - JavaScript Fwdays 3
Timur Shemsedinov
 
Node.js in 2021
Timur Shemsedinov
 
Information system structure and architecture
Timur Shemsedinov
 
Базы данных в 2020
Timur Shemsedinov
 
Почему хорошее ИТ-образование невостребовано рыночком
Timur Shemsedinov
 
Node.js security
Timur Shemsedinov
 
Ad

Recently uploaded (20)

PPTX
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
PPTX
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
PDF
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
PDF
MiniTool Partition Wizard Free Crack + Full Free Download 2025
bashirkhan333g
 
PDF
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 
PDF
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
PPTX
Transforming Mining & Engineering Operations with Odoo ERP | Streamline Proje...
SatishKumar2651
 
PDF
Generic or Specific? Making sensible software design decisions
Bert Jan Schrijver
 
PDF
4K Video Downloader Plus Pro Crack for MacOS New Download 2025
bashirkhan333g
 
PDF
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
PDF
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
PPTX
Empowering Asian Contributions: The Rise of Regional User Groups in Open Sour...
Shane Coughlan
 
PPTX
Milwaukee Marketo User Group - Summer Road Trip: Mapping and Personalizing Yo...
bbedford2
 
PPTX
Foundations of Marketo Engage - Powering Campaigns with Marketo Personalization
bbedford2
 
PPTX
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
PDF
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
PPTX
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
PPTX
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
PDF
MiniTool Partition Wizard 12.8 Crack License Key LATEST
hashhshs786
 
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
MiniTool Partition Wizard Free Crack + Full Free Download 2025
bashirkhan333g
 
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
Transforming Mining & Engineering Operations with Odoo ERP | Streamline Proje...
SatishKumar2651
 
Generic or Specific? Making sensible software design decisions
Bert Jan Schrijver
 
4K Video Downloader Plus Pro Crack for MacOS New Download 2025
bashirkhan333g
 
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
Empowering Asian Contributions: The Rise of Regional User Groups in Open Sour...
Shane Coughlan
 
Milwaukee Marketo User Group - Summer Road Trip: Mapping and Personalizing Yo...
bbedford2
 
Foundations of Marketo Engage - Powering Campaigns with Marketo Personalization
bbedford2
 
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
MiniTool Partition Wizard 12.8 Crack License Key LATEST
hashhshs786
 

Node.js in 2020 - part 1

  • 1. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) Node.js in 2020 #1 Выйди и зайди нормально Timur Shemsedinov github.com/HowProgrammingWorks github.com/tshemsedinov Chief Technology Architect at Metarhia Lecturer at Kiev Polytechnic Institute
  • 2. github.com/tshemsedinov https://youtube.com/TimurShemsedinov github.com/HowProgrammingWorks/Index Весь курс по ноде (>35.5 часов) https://habr.com/ru/post/485294/ t.me/HowProgrammingWorks t.me/NodeUA [email protected]
  • 3. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) Node.js Starter Kit no dependencies: 15kb size, with PG drivers + 1.2mb
  • 4. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Starter Kit Key Ideas ● Минимум кода и зависимостей ● Минимизация I/O, отдача всего из памяти ● Безопасность и изоляция контекстов ● Структура и архитектура приложения ● Разделение системного и прикладного слоя ● Все на контрактах (interface) ● Балансировка, таймауты и очередь запросов
  • 5. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Starter Kit Feature List ● Автороутинг API и поддержка HTTP(S), WS(S) ● Подгрузка изменений на лету через fs.watch ● Загрузчик конфигурации и Graceful shutdown ● Утилизация CPU, кластеризация через потоки ● Слой доступа к данным DAL: Postgresql ● Сессии с сохраняемым состоянием ● Песочницы, потоки, масштабирование, тесты
  • 6. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) Node.js in 2020 State of the platform and future
  • 7. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Node.js уже 10 лет: v0.0.1 — 27 мая 2019 0.10.x и 0.12.x — (2013 - 2016) Io.js 1.x, 2.x, 3.x — (2014 - 2015) Argon 4.x (2015 - 2018), 5.x (2015 - 2016), Boron 6.x (2016 - 2019), 7.x (2016 - 2017), Carbon 8.x (2017 - 2019), 9.x (2017 - 2018), Dubnium 10.x (2018 - 2021),11.x (2018 - 2019), Erbium 12.x (2019 - 2022), 13.x (to June 2020) 14.x (April 2020 - April 2023), 15.x(2020-)
  • 8. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Node.js features 8.x V8 6.0, async/await, TurboFan and Ignition 10.x V8 6.6, HTTP/2, fs.promises, BigInt, npm 6 12.x V8 7.8, TLS 1.3, OpenSSL 1.1.1c, npm 6.10.3 js: #, static, async/await, async stack, динамическая куча, llhttp и llparser, threads, DOS в HTTP/2, startup, fs.rmdir & fs.Dir, process.resourceUsage()
  • 9. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Node.js features 13.x V8 7.8, npm 6.13.6, libuv 1.34.1 WASI, worker.resourceLimits, vm.Module Source map, Advanced Serialization API 14.x Ожидания: V8 8.x: больше доступа к v8 api HTTP/3 (HTTP over IETF QUIC) улучшения в WASI, N-API, async_hooks streams, в работе с workers и esm
  • 10. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Shared memory and Atomics Появилось в Node.js 9 ■ SharedArrayBuffer ■ Atomics ○ add, sub, and, or, xor ○ store, load, exchange, compareExchange ○ notify, wait, wake (deprecated)
  • 11. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Threads vs Processes process process JavaScript thread V8libuv node.js JavaScript thread V8 libuv node.js JavaScript thread V8 libuv node.js IPC
  • 12. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Why Isolation? ● Ошибки ● Утечки памяти и других ресурсов ● Приложение: данные, соединения с БД ● Файловая система и корневой каталог ● Окружение ОС, PID, IPC ● Безопасность ОС: пользователи, группы ● Сеть: дескрипторы сокетов, порты, хосты
  • 13. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Execution Strategy Problems ● Недостаточная изоляция исполнения запросов к серверу друг от друга ● Один неудачный запрос может убить все параллельно исполняемые ● В асинхронной среде сложно найти и связать ошибку с запросом ● Изоляция приложений и организаций в SaaS
  • 14. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Execution Isolation ● VPS (виртуальная машина) ● Контейнер (Docker) ● Провесс (node) ● Поток (встроенный модуль worker_threads) ● Песочница (vm.createContext, vm.Script) ● Программная абстракция (объект или замыкание)
  • 15. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Links Node https://nodejs.org/en/about/releases/ https://nodejs.org/en/blog/ https://node.green/ Deno https://github.com/denoland/deno https://youtu.be/z6JRlx5NC9E
  • 16. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Deno ● Безопасность: файловая система, сеть, окружение ● V8, TypeScript ● Rust вместо C++ ● Tokio (event loop, I/O scheduler) ● Встроенный менеджер пакетов
  • 17. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Node.js Готовность ноды для серьезных систем Проблемы ноды ● Безопасность, заражения, зависимости ● Потерянные ошибки, утечки, перезапуски ● Асинхронность и стектрейс Перспективы платформы
  • 18. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) v8 Serialization API v8.serialize, v8.deserialize v8.Serializer, v8.Deserializer
  • 19. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Race Condition const v8 = require('v8'); const dataset = [ { name: 'Marcus Aurelius', born: 121 }, { name: 'Mao Zedong', born: 1893 }, ]; const v8Data = v8.serialize(dataset); const obj = v8.deserialize(v8Data);
  • 20. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c v8 Serialization
  • 21. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) vm Sandboxing vm.Script, vm.runInContext and v8::Context
  • 22. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c vm.createContext const vm = require('vm'); const sandbox = { console: new Logger(), require: wrap(require), application: new Application(), }; sandbox.global = sandbox; vm.createContext(sandbox);
  • 23. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c vm.Script const vm = require('vm'); const fs = require('fs'); const code = await fs.readFile(fileName, 'utf8'); const src = `'use strict';n context => ${code}`; const script = new vm.Script(src); script.runInContext(sandbox, { timeout: 5000 });
  • 24. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c vm.Script const options = { timeout: 5000, displayErrors: false, // default: true breakOnSigint: true, // default: false, CTRL+C }; script.runInContext(sandbox, options); const object = { /* global */ }; script.runInNewContext(object, options); script.runInThisContext(options);
  • 25. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) ES.Next ECMAScript 2020
  • 26. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c ES.Next features ● Приватные и статические поля ● Изменения в Array, Object, String ● Atomics и SheredArrayBuffer ● Коллекции Set, Map, WeakSet, WeakMap ● globalThis ● Math
  • 27. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Operators Rest const f = (a, b, ...array) => {}; const g = ({ a, b, ...array }) => {}; const { name, ...rest } = obj; Spread f(a, b, ...array); const obj2 = { name, ...obj1 }; const clone = { ...obj };
  • 28. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Operators Exponentiation Math.pow(x, y) x ** y x **= y x = x ** y Optional chaining const spqr = { emperor: { name: 'Marcus' } }; console.log(spqr.emperor?.name); console.log(spqr.president?.name);
  • 29. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Operators Exponentiation Math.pow(x, y) x ** y x **= y x = x ** y Optional chaining (still waiting v8 8.x in Node.js) const spqr = { emperor: { name: 'Marcus' } }; console.log(spqr.emperor?.name); console.log(spqr.president?.name);
  • 30. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Asynchronous iterable contract Symbol.iterator iterable[Symbol.iterator]() Symbol.asyncIterator asyncIterable[Symbol.asyncIterator]()
  • 31. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Try...catch try { throw new Error('message'); } catch { console.log('no arguments catched'); }
  • 32. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Function ((a, b) => { const c = a + b; // hello there return c; }).toString() "(a, b) => { const c = a + b; // hello there return c; }"
  • 33. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Promise.finally new Promise(executor) .then(onFulfilled[, onRejected]) .catch(onRejected) .finally(onFinally);
  • 34. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Promise.allSettled const p1 = Promise.resolve('p1'); const p2 = new Promise((resolve, reject) => { setTimeout(resolve, 1000, 'p2'); }); const p3 = new Promise((resolve, reject) => { setTimeout(reject, 100, 'p3'); }); Promise.all([p1, p2, p3]).then(values => { console.log(values); });
  • 35. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Promise.allSettled Promise.all([p1, p2, p3]).then(values => { console.log(values); }); node:26549) UnhandledPromiseRejectionWarning: p3 (node:26549) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:26549) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  • 36. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Promise.allSettled const p1 = Promise.resolve('p1'); const p2 = new Promise((resolve, reject) => { setTimeout(resolve, 1000, 'p2'); }); const p3 = new Promise((resolve, reject) => { setTimeout(reject, 100, 'p3'); }); Promise.allSettled([p1, p2, p3]).then(values => { console.log(values); });
  • 37. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Promise.allSettled Promise.allSettled([p1, p2, p3]).then(values => { console.log(values); }); [ { status: 'fulfilled', value: 'p1' }, { status: 'fulfilled', value: 'p2' }, { status: 'rejected', reason: 'p3' } ]
  • 38. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) Состояние гонки В параллельном и асинхронном программировании
  • 39. Web Locks API in node.js & browser Timur Shemsedinov Chief Technology Architect at Metarhia Lecturer at KPI
  • 40. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Why do we need Web Locks API ? — Do you know what is mutex, locks, critical section, race condition, parallel programming at all? — Congrats! It’s is very likely that all your JavaScript code broken )))
  • 41. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Concurrent Computing
  • 42. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Concurrency Problems ● Race condition ● Deadlock ● Livelock ● Resource starvation ● Resource leaks
  • 43. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Synchronization Primitives Semaphore Binary semaphore Counting semaphore Condition variable Spinlock Mutex Timed mutex Shared mutex Recursive mutex Monitor Barrier
  • 44. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Links Spec: wicg.github.io/web-locks MDN: developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API Implementation: github.com/metarhia/web-locks Examples: github.com/HowProgrammingWorks/RaceCondition github.com/HowProgrammingWorks/Semaphore github.com/HowProgrammingWorks/Mutex Async prog: habr.com/ru/post/452974/
  • 46. github.com/tshemsedinov https://youtube.com/TimurShemsedinov github.com/HowProgrammingWorks/Index Весь курс по ноде (>35.5 часов) https://habr.com/ru/post/485294/ t.me/HowProgrammingWorks t.me/NodeUA [email protected]