Например, Stateless означает, что каждый запрос содержит всю необходимую информацию для его обработки, а Cacheable позволяет кэшировать ответы и снижать нагрузку на сервер.
На картинке — основные принципы REST: Client-Server, Stateless, Uniform Interface, Cacheable, Layered System и Code on Demand, а также примеры HTTP-методов и взаимодействия клиента с сервером.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤6👍6
ArrayBuffer.transfer() — переносим содержимое буфера!
При обработке файлов, изображений, аудио и сетевых данных часто приходится изменять размер бинарного буфера или передавать его содержимое в новый
Для начала создадим небольшой буфер и запишем в него четыре значения:
Теперь перенесём содержимое в новый буфер:
Метод возвращает новый
Проверим, что значения сохранились после переноса:
Новый
Во время переноса можно сразу указать новый размер:
При увеличении размера существующее содержимое сохраняется, а дополнительная область заполняется нулями. Что удобно для постепенно растущих бинарных данных: не требуется отдельно создавать буфер нужного размера и вызывать
Уменьшение выполняется тем же способом:
Если новый размер меньше исходного, в результирующем буфере остаются только байты, которые помещаются в заданную длину. Буфер
🔥
📣 JS Ready | #практика
При обработке файлов, изображений, аудио и сетевых данных часто приходится изменять размер бинарного буфера или передавать его содержимое в новый
ArrayBuffer. Обычно для этого нужно создать новый буфер и вручную скопировать байты, а transfer() объединяет эти действия в одну операцию.Для начала создадим небольшой буфер и запишем в него четыре значения:
const buffer = new ArrayBuffer(8);
const bytes = new Uint8Array(buffer);
bytes.set([10, 20, 30, 40]);
console.log(bytes);
ArrayBuffer хранит непосредственно бинарные данные, а Uint8Array предоставляет представление для чтения и записи отдельных байтов. Оба объекта используют одну область памяти, поэтому изменения через bytes сразу отражаются в buffer.Теперь перенесём содержимое в новый буфер:
const moved = buffer.transfer();
console.log(moved.byteLength); // 8
console.log(buffer.byteLength); // 0
Метод возвращает новый
ArrayBuffer, содержащий прежние данные. Исходный буфер при этом отсоединяется: его длина становится равной нулю, а все созданные поверх него представления больше не дают доступа к переданной памяти. Это отличие от обычного клонирования, при котором исходная и новая копии продолжают существовать независимо.Проверим, что значения сохранились после переноса:
const movedBytes = new Uint8Array(moved);
console.log([...movedBytes]);
// [10, 20, 30, 40, 0, 0, 0, 0]
Новый
Uint8Array создаётся уже поверх moved. Первые четыре байта содержат записанные значения, а оставшаяся часть буфера по-прежнему заполнена нулями.Во время переноса можно сразу указать новый размер:
const expanded = moved.transfer(16);
console.log(expanded.byteLength); // 16
console.log([...new Uint8Array(expanded)]);
При увеличении размера существующее содержимое сохраняется, а дополнительная область заполняется нулями. Что удобно для постепенно растущих бинарных данных: не требуется отдельно создавать буфер нужного размера и вызывать
TypedArray#set() для ручного копирования.Уменьшение выполняется тем же способом:
const trimmed = expanded.transfer(4);
console.log(trimmed.byteLength); // 4
console.log([...new Uint8Array(trimmed)]);
// [10, 20, 30, 40]
Если новый размер меньше исходного, в результирующем буфере остаются только байты, которые помещаются в заданную длину. Буфер
expanded, как и предыдущие исходные буферы, после переноса становится отсоединённым.ArrayBuffer.transfer() полезен там, где нужно передать владение бинарными данными или изменить размер буфера без ручного копирования. При этом важно помнить, что после каждого переноса исходный буфер становится недоступен для дальнейшего использования.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤6👍4🤝3
Например,
then() используется для обработки успешного выполнения, catch() — для ошибок, а finally() позволяет выполнить код независимо от результата.На картинке собраны основные методы Promise, работа с цепочками, обработка ошибок, состояния
pending, fulfilled и rejected, а также методы для работы с несколькими Promise — all(), allSettled(), race() и any().Сохрани, чтобы было под рукой!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍9❤5🤝2
Шпаргалка по основным возможностям 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