Шпаргалка по основным возможностям Iterator API: ручное управление итерацией, досрочное завершение и передача ошибок, создание iterable-объектов и ленивые преобразования через Iterator Helpers. Полезная база для углубления знаний об итераторах, генераторах и обработке последовательностей данных.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍7🤝5❤2
В этой статье:
• Узнаете, как сегодня разрабатывать программы и игры для легендарного Atari ST 1985 года;• Разберёте оптимизацию кода под Motorola 68000 с помощью C и ассемблера;• Посмотрите, как автор портировал DOOM на Atari ST и заставил его работать на железе с 8 МГц и несколькими мегабайтами памяти.Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤6🔥4🤝2
Например,
Promise.then() выполняется через Microtask Queue и имеет более высокий приоритет, чем setTimeout(), который попадает в Task Queue. На картинке — основные компоненты JavaScript Event Loop:
Call Stack, Web APIs, Microtask Queue, Task Queue и сам цикл событий, который управляет выполнением синхронных и асинхронных операций.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍5🤝5❤1
Например,
git merge используется для объединения веток с сохранением полной истории изменений, а git rebase позволяет перенести коммиты на новую базу и сделать историю проекта более линейной.На картинке показана разница между двумя подходами работы с ветками Git: как выглядит история коммитов после
merge, где появляется отдельный merge-коммит, и после rebase, где изменения перестраиваются поверх актуальной ветки.Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍7❤5
Не синхронизируйте состояние — вычисляйте его!
Одна из частых причин багов — хранить одно и то же состояние в нескольких представлениях:
Рано или поздно один участок кода изменит
Если значение однозначно получается из других данных — вычисляйте его:
Тот же принцип работает для отфильтрованных списков,
Если вычисление действительно дорогое, тогда уже имеет смысл мемоизировать его — но не создавать второе изменяемое состояние:
🔥 Чем меньше состояний приходится синхронизировать вручную, тем меньше невозможных комбинаций может появиться в программе.
📣 JS Ready | #совет
Одна из частых причин багов — хранить одно и то же состояние в нескольких представлениях:
let items = [];
let total = 0;
items.push(product);
// Теперь нужно не забыть обновить total
Рано или поздно один участок кода изменит
items, но забудет обновить total. Появляются два источника истины.Если значение однозначно получается из других данных — вычисляйте его:
const total = items.reduce(
(sum, item) => sum + item.price,
0
);
Тот же принцип работает для отфильтрованных списков,
isEmpty, количества элементов, доступных действий и других производных значений.Если вычисление действительно дорогое, тогда уже имеет смысл мемоизировать его — но не создавать второе изменяемое состояние:
const visibleUsers = users.filter(
user => user.active && user.role === role
);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥7❤5
Например, Redis используется как быстрый in-memory cache для хранения часто запрашиваемых данных, сессий и временных значений, чтобы уменьшить нагрузку на базу данных. А CDN Cache позволяет отдавать статический контент ближе к пользователю, сокращая задержки и количество запросов к основному серверу.
На картинке — основные уровни кэширования в современных системах.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤7🔥5
Используйте Proxy для создания объектов с поведением, а не просто данных!
Многие используют объекты только как хранилище:
Но иногда нужно, чтобы объект сам выполнял логику при чтении или изменении данных.
Для этого в JavaScript есть
Теперь обычное обращение к свойству запускает вашу логику:
Можно создавать объекты с автоматическими значениями:
Или автоматически валидировать изменения:
Теперь:
Такой подход используется внутри Vue 3 для реактивности, а также часто применяется в SDK, конфигурациях и слоях валидации.
🔥
📣 JS Ready | #совет
Многие используют объекты только как хранилище:
const config = {
theme: 'dark',
lang: 'ru'
};Но иногда нужно, чтобы объект сам выполнял логику при чтении или изменении данных.
Для этого в JavaScript есть
Proxy.const user = new Proxy({}, {
get(target, property) {
console.log(`Reading ${property}`);
return target[property];
}
});Теперь обычное обращение к свойству запускает вашу логику:
user.name;
Можно создавать объекты с автоматическими значениями:
const settings = new Proxy({}, {
get(target, key) {
return target[key] ?? 'default';
}
});
console.log(settings.theme);
// defaultИли автоматически валидировать изменения:
const user = new Proxy({}, {
set(target, key, value) {
if (key === 'age' && value < 0) {
throw new Error('Invalid age');
}
target[key] = value;
return true;
}
});Теперь:
user.age = -5;
// Error
Такой подход используется внутри Vue 3 для реактивности, а также часто применяется в SDK, конфигурациях и слоях валидации.
Proxy позволяет превращать обычные объекты JavaScript в объекты с собственной логикой поведения, не меняя код, который с ними работает.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍5🤝5❤1
Разбираем Proxy API, с помощью которого можно перехватывать и переопределять базовые операции с объектами и функциями: контролировать доступ и изменение данных, управлять видимостью и перечислением свойств, отслеживать вызовы функций и создание экземпляров. Используется для валидации, логирования, метапрограммирования и создания гибкого поведения объектов.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥9🤝4❤2
Создаём индекс данных из массива для быстрого поиска через Map!
При работе с данными из API часто требуется получать элементы массива по идентификатору. Самый простой вариант — использовать
Например, поиск пользователя по
Метод
Для единичного поиска этого достаточно. Но если выполнять такие операции внутри циклов или часто обращаться к одним и тем же данным, появляется лишняя нагрузка: каждый вызов снова проходит массив от начала до нужного элемента.
Вместо этого можно заранее создать индекс, где идентификатор будет использоваться как ключ, а объект — как значение:
Теперь получение пользователя выполняется через ключ без повторного перебора массива.
По сложности подходы отличаются:
Поэтому такой паттерн особенно полезен при работе с большими коллекциями и частыми операциями чтения.
Например, пользователи и их настройки могут приходить отдельными запросами:
После создания индекса можно собрать итоговую структуру данных без вложенных поисков внутри массива:
В результате каждый объект получает связанные данные через быстрый поиск по ключу. Такой подход часто применяется при подготовке данных для таблиц, списков, кэширования результатов запросов, нормализации состояния приложения и работе с большими наборами данных.
Для создания индекса также можно использовать обычный объект:
Однако
Важно учитывать, что индекс — это дополнительная структура в памяти. Если нужен один поиск, обычный
🔥 Создание индекса из массива позволяет заранее подготовить данные для быстрого доступа и избежать повторных линейных поисков при обработке коллекций.
📣 JS Ready | #практика
При работе с данными из API часто требуется получать элементы массива по идентификатору. Самый простой вариант — использовать
find(), но при большом количестве повторных поисков такой подход приводит к постоянному перебору коллекции.Например, поиск пользователя по
id:const users = [
{
id: 1,
name: "Alex"
},
{
id: 2,
name: "John"
}
];
const user = users.find(
user => user.id === 2
);
console.log(user);
Метод
find() последовательно проверяет элементы массива и возвращает первое совпадение.Для единичного поиска этого достаточно. Но если выполнять такие операции внутри циклов или часто обращаться к одним и тем же данным, появляется лишняя нагрузка: каждый вызов снова проходит массив от начала до нужного элемента.
Вместо этого можно заранее создать индекс, где идентификатор будет использоваться как ключ, а объект — как значение:
const usersById = new Map(
users.map(user => [
user.id,
user
])
);
console.log(
usersById.get(2)
);
Теперь получение пользователя выполняется через ключ без повторного перебора массива.
По сложности подходы отличаются:
find() - O(n)
Map.get() - O(1) в среднем
Поэтому такой паттерн особенно полезен при работе с большими коллекциями и частыми операциями чтения.
Например, пользователи и их настройки могут приходить отдельными запросами:
const settings = [
{
userId: 1,
theme: "dark"
},
{
userId: 2,
theme: "light"
}
];
const settingsByUser = new Map(
settings.map(item => [
item.userId,
item
])
);
После создания индекса можно собрать итоговую структуру данных без вложенных поисков внутри массива:
const result = users.map(user => ({
...user,
settings: settingsByUser.get(user.id)
}));
console.log(result);В результате каждый объект получает связанные данные через быстрый поиск по ключу. Такой подход часто применяется при подготовке данных для таблиц, списков, кэширования результатов запросов, нормализации состояния приложения и работе с большими наборами данных.
Для создания индекса также можно использовать обычный объект:
const usersById = Object.fromEntries(
users.map(user => [
user.id,
user
])
);
console.log(usersById[2]);
Однако
Map лучше подходит для динамических коллекций, где требуется часто добавлять, удалять или получать элементы. Кроме того, он поддерживает любые типы ключей, имеет встроенное свойство size и не зависит от прототипа объекта.Важно учитывать, что индекс — это дополнительная структура в памяти. Если нужен один поиск, обычный
find() может быть проще и понятнее. Но при многократном доступе к данным создание индекса позволяет значительно сократить количество лишних операций.Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍6🔥5
Например, Smoke Testing проверяет, что критичные эндпоинты вообще доступны, а Contract Testing помогает убедиться, что запросы и ответы по-прежнему соответствуют API-контракту.
На картинке — 9 основных видов API-тестирования: от функциональных и интеграционных тестов до нагрузочного, security- и fuzz-тестирования.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍7🤝3❤1
JavaScript умеет освобождать ресурсы сам, без finally!
Когда код временно открывает ресурс, соединение, файл,
Современный JS поддерживает явное управление ресурсами. Объект может определить
После этого управление жизненным циклом ресурса становится некой частью языка:
Для ресурсов с асинхронной очисткой существует отдельная пара
🔥
📣 JS Ready | #совет
Когда код временно открывает ресурс, соединение, файл,
lock или подписку — его обязательно нужно закрыть даже при ошибке. Обычно для этого пишут try/finally:const connection = openConnection();
try {
await connection.query(sql);
} finally {
connection.close();
}
Современный JS поддерживает явное управление ресурсами. Объект может определить
Symbol.dispose, а using гарантированно вызовет его при выходе из области видимости:function openConnection() {
return {
query(sql) {
return db.query(sql);
},
[Symbol.dispose]() {
db.close();
}
};
}После этого управление жизненным циклом ресурса становится некой частью языка:
{
using connection = openConnection();
await connection.query(sql);
}
// connection[Symbol.dispose]() уже вызванДля ресурсов с асинхронной очисткой существует отдельная пара
await using и Symbol.asyncDispose:await using connection = await connect();
await connection.query(sql);
// await connection[Symbol.asyncDispose]()
using полезен для ресурсов с чётким временем жизни: файлов, соединений, блокировок и временных подписок. Жизненным циклом управляет сам scope.Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥5🤝4
Например, балансировщик нагрузки распределяет входящий трафик между серверами, кэширование снижает нагрузку на базу данных, а очереди сообщений позволяют сервисам работать асинхронно и меньше зависеть друг от друга.
На картинке — 12 архитектурных концепций, которые полезно знать разработчику: от CDN и API Gateway до шардинга, consistent hashing и автомасштабирования.
Сохрани, чтобы была под рукой!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🤝8❤5
Одинаковый синтаксис
..., но разные задачи: Spread раскрывает элементы и свойства, а Rest собирает оставшиеся значения в массив или объект.На картинке — различия, синтаксис и примеры использования Spread и Rest при работе с массивами, объектами и функциями.
Сохрани как краткую памятку!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥9🤝4❤1
Array.prototype.fill() — заполнение массивов и особенности работы со ссылками!
Метод принимает три аргумента:
Один из распространённых вариантов использования — создание массивов состояний:
Такой подход используется в алгоритмах с индексами, графах, таблицах состояний и буферных структурах.
Главная особенность
Результат:
Все элементы ссылаются на один объект. Для создания независимых значений необходимо генерировать объект для каждой позиции:
Также
Метод поддерживает отрицательные индексы:
📣 JS Ready | #практика
Array.prototype.fill() — часто используемый метод, который заменяет элементы массива указанным значением. Он изменяет исходный массив и применяется при подготовке структур данных, создании массивов фиксированной длины и инициализации состояний. Пример:const numbers = new Array(5).fill(0);
console.log(numbers);
// [0, 0, 0, 0, 0]
Метод принимает три аргумента:
array.fill(value, start, end);
value — значение для заполнения, start — индекс начала изменения, end — граница диапазона без включения самого индекса. Например:const values = [10, 20, 30, 40, 50];
values.fill(1, 2, 4);
console.log(values);
// [10, 20, 1, 1, 50]
Один из распространённых вариантов использования — создание массивов состояний:
const visited = new Array(100).fill(false);
visited[25] = true;
Такой подход используется в алгоритмах с индексами, графах, таблицах состояний и буферных структурах.
Главная особенность
fill() проявляется при работе с объектами. Метод не создаёт отдельные экземпляры, а записывает одно и то же значение во все позиции массива:const items = new Array(3).fill({
active: false
});
items[0].active = true;
console.log(items);Результат:
[
{ active: true },
{ active: true },
{ active: true }
]
Все элементы ссылаются на один объект. Для создания независимых значений необходимо генерировать объект для каждой позиции:
const items = Array.from(
{ length: 3 },
() => ({
active: false
})
);
Также
fill() изменяет разреженные массивы, создавая реальные индексные свойства:const array = new Array(3);
console.log(Object.keys(array));
// []
array.fill(null);
console.log(Object.keys(array));
// ["0", "1", "2"]
Метод поддерживает отрицательные индексы:
const numbers = [1, 2, 3, 4, 5];
numbers.fill(0, -2);
console.log(numbers);
// [1, 2, 3, 0, 0]
Array.prototype.fill() не выполняет копирование значений. Для примитивов поведение обычно ожидаемое, но при работе с объектами и массивами необходимо учитывать ссылочную модель JavaScript. Метод, который хорошо показывает важный принцип языка: в JavaScript значение и ссылка на объект — это разные вещи.Please open Telegram to view this post
VIEW IN TELEGRAM
🤝8❤6👍4
Event Sourcing меняет привычный подход к хранению данных: вместо перезаписи текущего состояния система сохраняет последовательность событий, из которых это состояние можно восстановить.В этом посте:
• Разберём, почему в Event Sourcing состояние становится производным;
• Отделим команды от событий и поймём их разные роли;
• Реализуем восстановление состояния через последовательный replay событий;
• Разберём, почему события становятся источником истины, а не просто журналом изменений.
Такой подход сохраняет не только результат изменений, но и их причинную историю, позволяя строить новые представления данных и воспроизводить состояние системы на основе событий.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍6❤3