JavaScript Ready | Программирование
8.32K subscribers
1K photos
60 videos
537 links
Авторский канал по разработке на JavaScript.
Ресурсы, обучения, задачи, шпаргалки.
Ежедневно информация пополняется!

Cотрудничество: @energy_c
Download Telegram
📱 Web Workers — выполнение кода в отдельном потоке!

Разбираем Web Workers, с помощью которых можно выполнять ресурсоёмкие задачи вне основного UI-потока: запускать фоновые вычисления, передавать данные между main thread и Worker, получать результаты, обрабатывать ошибки и управлять завершением Worker. Используется для тяжёлых вычислений и обработки больших объёмов данных без блокировки интерфейса.

📣 JS Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍9🔥5
Выполняйте независимые операции без эффекта домино!

Если несколько операций не зависят друг от друга, Promise.all() может создать лишнюю связанность: одна ошибка отклоняет общий Promise, хотя остальные задачи продолжат выполняться и могут успешно завершиться.
const users = await Promise.all(
ids.map(id => loadUser(id))
);


Для независимых задач используйте Promise.allSettled() — он дождётся каждой и сохранит результат отдельно:
const results = await Promise.allSettled(
ids.map(id => loadUser(id))
);

const successful = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);


Что полезно для пакетной отправки, фоновых задач и загрузки независимых данных: ошибка одной операции не скрывает успешные результаты остальных.

🔥 Если операции независимы, не позволяйте одной ошибке скрывать результат остальных — обрабатывайте каждую отдельно.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍5🤝3❤1
❤️ Немного ностальгии и чистого JS в статье на Хабре: «TAMA-90: тамагочи из 90-х своими руками на JavaScript»!

В этой статье:
• Показывается, как с нуля собрать браузерного тамагочи на HTML, CSS и JavaScript — без фреймворков, npm и сборщиков;
• Разбираются игровое состояние, жизненный цикл питомца, случайные события, мини-игра, коллекция и сохранение прогресса через localStorage;
• Объясняется, как рисовать пиксельных персонажей программно через Canvas и создавать звуки через Web Audio API без готовых изображений и аудиофайлов.

🔊 Продолжайте читать на Habr!


📣 JS Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🔥7👍5🤝2
📂 Шпаргалка по технологиям взаимодействия систем!

Например, REST используют для построения API, WebSocket — для двустороннего обмена данными, а gRPC — для взаимодействия между сервисами.

На картинке — основные технологии и подходы, с которыми регулярно сталкиваются разработчики: REST, Webhooks, GraphQL, SOAP, WebSocket, gRPC, MQTT, AMQP, SSE, EDI и EDA. Кратко и наглядно показано, чем они отличаются, как работают и для каких задач применяются.

Сохрани, чтобы не потерять!

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤5🤝5🔥2
📂 Как работает HTTP и HTTPS!

HTTP передаёт данные между клиентом и сервером без шифрования, а HTTPS добавляет TLS — он аутентифицирует сервер, согласовывает ключи и защищает дальнейший обмен данными шифрованием.

На картинке наглядно показано, чем отличается обычное HTTP-соединение от HTTPS: от TCP-handshake до установки защищённого соединения и передачи данных.

Сохрани, чтобы не потерять!

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤5🔥4🤝3
Используйте возвращаемое значение delete() вместо лишней проверки!

У Map.delete() и Set.delete() есть полезное свойство: метод возвращает true, только если элемент действительно существовал и был удалён.

Поэтому вместо двойного поиска:
if (cache.has(key)) {
cache.delete(key);
onRemoved(key);
}


можно сразу использовать результат удаления:
if (cache.delete(key)) {
onRemoved(key);
}


То же самое работает с Set:
if (activeUsers.delete(userId)) {
updateCounter();
}


Вы не выполняете сначала has(), а затем отдельный delete(). Сама операция удаления одновременно отвечает на вопрос, был ли элемент.

🔥 Не проверяйте коллекцию перед удалением, если проверка нужна только ради условия — delete() уже возвращает нужный результат.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥8❤3🤝2
Подписывайтесь на событие только один раз через once!

У addEventListener() есть опция once: обработчик автоматически удаляется после первого срабатывания. Без ручного removeEventListener():
button.addEventListener('click', handleClick, {
once: true
});


Особенно полезно для одноразовых действий: завершения анимации, первого взаимодействия, загрузки ресурса или ожидания ответа.
element.addEventListener('transitionend', () => {
element.remove();
}, { once: true });


Можно удобно превращать одноразовые события в Promise:
const once = (target, event) =>
new Promise(resolve =>
target.addEventListener(event, resolve, { once: true })
);

await once(video, 'ended');
console.log('Видео закончилось');


🔥 Для одноразового события используйте { once: true }. Если ждёте одно из нескольких — снимайте оставшиеся обработчики через AbortController.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤6🔥4
Как оплачивать зарубежные сервисы в 2026 году?

Можно бегать между посредниками и бояться блокировок после оплаты, а можно выпустить международную карту Lumio Pay и пользоваться любимыми сервисами без рисков.

— выпуск карты за 2 минуты
— лучший курс пополнения на рынке (у конкурентов на 20% выше)
— пополнение рублями или криптой
— чистые BIN карт, оплата без риска блокировок

Пока все ищут идеальное решение, оно у тебя перед глазами: @LumioPay
Почему forEach() не ждёт async-функцию?

forEach() не учитывает возвращаемое значение callback и не содержит механизма ожидания Promise. Поэтому передача async-callback не меняет модель выполнения метода: forEach() синхронно запускает callback для каждого элемента, не ожидая завершения созданных им асинхронных операций:
const users = [1, 2, 3];

users.forEach(async (id) => {
await saveUser(id);
});

console.log("Готово");


"Готово" будет выведено до завершения saveUser(). Каждый вызов async-callback возвращает Promise, но forEach() эти Promise не ожидает и не собирает.

Если операции должны выполняться последовательно, ожидание необходимо сделать частью самого цикла. Для этого подходит for...of с await:
for (const id of users) {
await saveUser(id);
}

console.log("Готово");


Следующая итерация начнётся только после завершения предыдущей. Такой вариант нужен, когда важен порядок выполнения или операции зависят друг от друга.

Для независимых операций можно сформировать массив Promise и дождаться их через Promise.all():
await Promise.all(
users.map((id) => saveUser(id))
);

console.log("Готово");


Promise.all() успешно выполняется после выполнения всех переданных Promise и отклоняется, если хотя бы один из них завершается с ошибкой. При этом остальные уже запущенные операции автоматически не отменяются.

Есть и важное следствие для обработки ошибок: внешний try...catch вокруг forEach() не перехватит последующее отклонение Promise из async-callback:
try {
users.forEach(async (id) => {
await saveUser(id);
});
} catch (error) {
console.error(error);
}


Для управляемой обработки ошибки необходимо ожидать Promise, представляющий выполнение асинхронных операций:
try {
await Promise.all(
users.map((id) => saveUser(id))
);
} catch (error) {
console.error(error);
}


🔥 Проблема не в async внутри forEach(), а в контракте самого метода: forEach() игнорирует возвращаемое значение callback и не ожидает Promise. Для последовательного выполнения используйте for...of с await, для конкурентного выполнения независимых операций — Promise.all().

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤6🔥6
📂 Шпаргалка по разработке API!

Например, REST используется для построения HTTP API, а OAuth 2.0 и JWT помогают организовать авторизацию и безопасную передачу данных.

На картинке — основные темы API-разработки: методы и коды ответов, типы API, безопасность, документация, тестирование, интеграция и API Gateway.

Сохрани, чтобы не потерять!

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍8❤4🤝1
Защищаем состояние от устаревших асинхронных результатов!

Порядок запуска асинхронных операций не определяет порядок их завершения. Если несколько вызовов обновляют одно состояние, более ранний запрос может завершиться позже и перезаписать актуальные данные:
let state;

async function loadUser(id) {
const user = await fetchUser(id);
state = user;
}

loadUser(1);
loadUser(2);


Если fetchUser(1) завершится после fetchUser(2), итоговым значением state станет пользователь 1, хотя последним был запущен loadUser(2).

Когда отмена предыдущей операции невозможна или не требуется, актуальность результата можно контролировать с помощью монотонно увеличивающейся версии:
let state;
let version = 0;

async function loadUser(id) {
const currentVersion = ++version;
const user = await fetchUser(id);

if (currentVersion !== version) {
return;
}

state = user;
}


Каждый запуск получает собственную версию, а version хранит версию последнего запуска. Если после await значения различаются, результат уже устарел и не должен изменять состояние.

При нескольких асинхронных этапах проверку следует выполнять после каждой границы, после которой выполнение может продолжиться с неактуальными данными:
async function loadUser(id) {
const currentVersion = ++version;

const user = await fetchUser(id);

if (currentVersion !== version) {
return;
}

const permissions = await fetchPermissions(user.id);

if (currentVersion !== version) {
return;
}

state = { user, permissions };
}


Проверка версии не отменяет уже выполняющуюся работу. Она определяет только то, сохраняет ли результат право влиять на текущее состояние:
loadUser(1); // version = 1
loadUser(2); // version = 2

// version = 1 игнорируется
// version = 2 может обновить state


🔥 Такой version token реализует семантику latest invocation wins: завершение асинхронной операции отделяется от актуальности её результата и предотвращает запись устаревших данных.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤6🤝3👍1