Всем привет!
В новой статье на Хабре мы углубились в тему Kotlin Coroutines — разобрали их основные концепции, способы работы с асинхронными операциями, управление потоком выполнения, обработку ошибок и исключений, а также многое другое. Получился очень полезный лонгрид.
Приятного чтения.
В новой статье на Хабре мы углубились в тему Kotlin Coroutines — разобрали их основные концепции, способы работы с асинхронными операциями, управление потоком выполнения, обработку ошибок и исключений, а также многое другое. Получился очень полезный лонгрид.
Приятного чтения.
Хабр
Работа с асинхронными операциями с помощью Kotlin Coroutines
Всем привет! Меня зовут Сергей, я Android-разработчик Студии Олега Чулакова на проектах Сбера. Недавно я написал статью Многопоточность в мобильной разработке . В ней был затронут один из наиболее...
🔥15👍3😱2
Всем привет!
Как правильно ответить на вопрос «Что такое чистая функция?», если различные источники дают разные трактовки? Кажется, мы нашли лучшее определение этому понятию. Следите за ходом мысли.
➡ Функция должна иметь только одну точку входа и только одну точку выхода из нее. Давайте назовем их ординарными, так как эти точки работают максимально ожидаемо. Следовательно, максимальная ожидаемая точка входа — это аргументы функции, а точка выхода — оператор return.
Почему только по одной точке на вход и выход?
⚫ Абсолютно любой другой вход в функцию — это использование внешних переменных, функций и т.д. — побочное действие.
⚫ Абсолютно любой другой выход из функции — присвоение значений внешним переменным, операции ввода/вывода, HTTP-запросы — побочное действие.
В итоге мы имеем следующее определение:
Чистая функция — это функция, которая имеет только одну ординарную точку входа (ее аргументы) и одну ординарную точку выхода (оператор return).
+1 понятие в вашу копилку.
@chulakov_dev
Как правильно ответить на вопрос «Что такое чистая функция?», если различные источники дают разные трактовки? Кажется, мы нашли лучшее определение этому понятию. Следите за ходом мысли.
Почему только по одной точке на вход и выход?
В итоге мы имеем следующее определение:
Чистая функция — это функция, которая имеет только одну ординарную точку входа (ее аргументы) и одну ординарную точку выхода (оператор return).
+1 понятие в вашу копилку.
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍2❤1
Какой функциональный объект в JS можно назвать функтором?
Anonymous Quiz
4%
Объект, реализующий метод sort
21%
Объект, реализующий метод map
25%
Объект, реализующий метод reduce
50%
Объект, реализующий метод next
👍13👏5❤2
Всем привет!
Давайте разберем вчерашний вопрос «Какой функциональный объект в JS можно назвать функтором?».
✅ Правильный ответ — вариант № 2: объект, реализующий метод map.
Объясняем, почему.
Функтор в JS — это объект, который получает некие значения, преобразует их с помощью внутренней чистой функции и возвращает результат с аналогичной структурой данных. Среди наших вариантов ответа такой метод только один, и это — map.
ℹ Теперь давайте рассмотрим другие варианты.
Sort — изменяет входной массив, т.е. он не является чистой функцией.
Reduce — также может вернуть аналогичную структуру, но это не гарантированно, т.к. он более универсален.
Next — метод для передачи данных следующей итерации, и он не используется для преобразования.
Если остались еще вопросы, задавайте.
@chulakov_dev
Давайте разберем вчерашний вопрос «Какой функциональный объект в JS можно назвать функтором?».
Объясняем, почему.
Функтор в JS — это объект, который получает некие значения, преобразует их с помощью внутренней чистой функции и возвращает результат с аналогичной структурой данных. Среди наших вариантов ответа такой метод только один, и это — map.
Sort — изменяет входной массив, т.е. он не является чистой функцией.
Reduce — также может вернуть аналогичную структуру, но это не гарантированно, т.к. он более универсален.
Next — метод для передачи данных следующей итерации, и он не используется для преобразования.
Если остались еще вопросы, задавайте.
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥4❤1🤔1
Привет, друзья!
🤔 Интересно, вы когда-нибудь слышали о методе requestIdleCallback?
Сегодня поговорим о нем.
⚫️ Метод requestIdleCallback очень редко используется, но в некоторых моментах он может значительно оптимизировать ваш код. Его суть заключается в следующем: метод принимает в качестве первого аргумента колбэк, который ставит в очередь Task Queue, и этот колбэк выполняется, когда браузер находится в режиме простоя.
Другими словами, когда браузеру «нечего делать», он может взять функцию, переданную через requestIdleCallback, и выполнить ее, тем самым не мешая выполнению других задач, когда это необходимо.
⚫️ Вторым аргументом он принимает дополнительные параметры, но пока реализован только один — timeout. В нем вы можете указать максимальное время (в миллисекундах), которое потребуется колбэку на выполнение. Если он не уложится в отведенное вами время, выполнение колбэка прервется.
Этот метод пока не поддерживается в Safari, но мы надеемся, что специалисты из Apple вскоре реализуют такую классную возможность.
@chulakov_dev
Сегодня поговорим о нем.
Другими словами, когда браузеру «нечего делать», он может взять функцию, переданную через requestIdleCallback, и выполнить ее, тем самым не мешая выполнению других задач, когда это необходимо.
Этот метод пока не поддерживается в Safari, но мы надеемся, что специалисты из Apple вскоре реализуют такую классную возможность.
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤4🔥4
Всем привет!
На рынке веб-разработки существует множество CMS с готовой административной панелью и набором базовых функций, таких как WordPress, 1C-Bitrix, Joomla и другие.
Но иногда требуется реализовать проект с индивидуальным дизайном и функционалом. В таком случае на помощь приходят Headless CMS. Они содержат серверную часть, API и базу данных, которая используется для хранения контента.
Одной из популярных Headless CMS с открытым исходным кодом является Strapi. Сегодня мы соберем свой образ для использования в проектах.
👉🏻 Читать пошаговую инструкцию
@chulakov_dev
На рынке веб-разработки существует множество CMS с готовой административной панелью и набором базовых функций, таких как WordPress, 1C-Bitrix, Joomla и другие.
Но иногда требуется реализовать проект с индивидуальным дизайном и функционалом. В таком случае на помощь приходят Headless CMS. Они содержат серверную часть, API и базу данных, которая используется для хранения контента.
Одной из популярных Headless CMS с открытым исходным кодом является Strapi. Сегодня мы соберем свой образ для использования в проектах.
👉🏻 Читать пошаговую инструкцию
@chulakov_dev
🔥22👍4❤3
Всем привет!
При разработке frontend-приложений важно учитывать ситуации, когда данные от backend еще не доступны. React Query и его хук
Один из ключевых параметров, на который следует обратить внимание, —
Вы можете думать, что проверка
Даже если проверка
@chulakov_dev
При разработке frontend-приложений важно учитывать ситуации, когда данные от backend еще не доступны. React Query и его хук
useQuery предлагают инструменты для управления этим процессом.Один из ключевых параметров, на который следует обратить внимание, —
isLoading. Он показывает, выполняется ли запрос данных. Если обратиться к data без проверки isLoading, это может вызвать ошибку, так как данные могут быть еще недоступны.const { isLoading, error, data } = useQuery('myData', fetchData);
Правильное использование isLoading включает проверку его значения перед применением данных, как показано в примере:function MyComponent() {
const { isLoading, error, data } = useQuery('myData', fetchData);
if (isLoading) return 'Загрузка...';
if (error) return `Произошла ошибка: ${error.message}`;
return (
<div>
<h1>{data.noscript}</h1>
<p>{data.denoscription}</p>
</div>
);
}
Здесь, если isLoading = true, компонент просто отображает сообщение «Загрузка...», а использование данных начинается только после их успешной загрузки.Вы можете думать, что проверка
isLoading не всегда необходима и в некоторых случаях можно использовать опциональную цепочку (optional chaining). Однако это может быть опасно. Если данные еще не получены, а мы пытаемся передать их в компонент, ожидающий конкретные данные, это может привести к ошибке. Вот пример:function MyOtherComponent({ noscript, denoscription }) {
return (
<div>
<h1>{noscript}</h1>
<p>{denoscription}</p>
</div>
);
}
function MyComponent() {
const { data } = useQuery('myData', fetchData);
return (
<MyOtherComponent noscript={data?.noscript} denoscription={data?.denoscription} />
);
}
В этом случае, если данные еще не получены, опциональная цепочка вернет undefined для data?.noscript и data?.denoscription, что может вызвать ошибку в MyOtherComponent.Даже если проверка
isLoading может показаться излишней, это важный шаг для обеспечения стабильности и надежности вашего приложения, и его не следует игнорировать.@chulakov_dev
🔥17👍5❤3🤔2
Как добавить изменения в последний коммит, не создавая новый и не изменяя его описания?
Anonymous Quiz
5%
git commit --current-message
3%
git commit -t
69%
git commit --amend --no-edit
23%
git commit --amend -m false
🔥10❤8👍6🤯1
Всем привет!
Многие из вас наверняка знают про метод stopPropagation. Он связан с таким понятием, как event bubbling, а сам он останавливает действие всплытия/погружения наступившего события.
Но (для нас это не было неожиданностью) почти никто не знает о его брате — методе stopImmediatePropagation. Он используется намного реже stopPropagation, но знать о нем нужно и важно.
➡ Метод stopImmediatePropagation останавливает все всплытия/погружения всех событий на определенном HTML-элементе. Допустим, если один элемент регистрирует у себя несколько событий, например от нескольких дочерних элементов, и они все начинают всплывать, то метод stopPropagation остановит только один из них, а stopImmediatePropagation — все.
В реальной разработке всплытие нескольких событий на одном элементе, конечно, антипаттерн, но кто знает, с какими трудностями вам придется столкнуться. Как минимум, будет чем удивить на собеседовании.
@chulakov_dev
Многие из вас наверняка знают про метод stopPropagation. Он связан с таким понятием, как event bubbling, а сам он останавливает действие всплытия/погружения наступившего события.
Но (для нас это не было неожиданностью) почти никто не знает о его брате — методе stopImmediatePropagation. Он используется намного реже stopPropagation, но знать о нем нужно и важно.
В реальной разработке всплытие нескольких событий на одном элементе, конечно, антипаттерн, но кто знает, с какими трудностями вам придется столкнуться. Как минимум, будет чем удивить на собеседовании.
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥5❤4
Всем привет!
Сегодня хотим рассказать интересный факт о скорости разных циклов. Вы знали, что forEach работает быстрее обычного for в 2–4 раза?
➡ Вот доказательство:
➡ Почему так происходит: for для работы своих итераций требуется каждый раз создавать переменную с текущим индексом, в то время как forEach обращается к элементу массива по его внутреннему индексу, а это гораздо быстрее.
Реальная разница будет наблюдаться при работе с большими данными, что в нашей работе совсем не редкость, так что знание этого факта может ускорить работу вашего кода.
@chulakov_dev
Сегодня хотим рассказать интересный факт о скорости разных циклов. Вы знали, что forEach работает быстрее обычного for в 2–4 раза?
const arr = new Array(10000).fill(0).map((_, i) => i);
function forFn() {
let res;
for (let i = 0; i < arr; i++) res = arr[i];
}
function forEachFn() {
let res;
arr.forEach(item => res = item);
}
function calculateLoopTime(callback) {
const time = performance.now();
callback();
console.log(performance.now() - time);
}
calculateLoopTime(forFn); // от 0.3s до 0.7s
calculateLoopTime(forEachFn); // от 0 до 0.3s
Реальная разница будет наблюдаться при работе с большими данными, что в нашей работе совсем не редкость, так что знание этого факта может ускорить работу вашего кода.
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥7❤3
Привет, друзья!
Сегодня мы коснемся важной темы: как правильно использовать key при рендеринге списков в React.
🔑 Key — это специальный атрибут для эффективного сопоставления элементов при изменении списка (и не только, но сейчас не об этом). Он критически важен для оптимальной производительности.
Проще всего в качестве ключа указать индекс элемента в массиве, однако подобный подход равносилен полному отсутствию ключа. Иногда это не приводит к проблемам, например, если ваш функционал предусматривает только добавление нового элемента в конец или ваш список абсолютно статичен.
Однако вы рискуете столкнуться с трудноуловимыми багами и лишними перерендерами при сортировке, фильтрации или добавлении элементов в начало списка. Все дело в том, что без уникальных ключей React не сможет правильно сопоставить старую и новую версии вашего списка.
❓ Как же решить эту проблему и обезопасить себя?
Используйте уникальные ID в качестве ключей. Если данные приходят с бэкенда, они, вероятно, уже имеют ID. На клиентской стороне вы можете указать сами уникальные идентификаторы или использовать библиотеку Nanoid для генерации, но делать это нужно не в момент рендера, а при определении массива. Кстати, по этой же причине и не рекомендуется применять метод Date.now().
Может показаться, что использовать Date.now() в качестве уникального ID — это быстрый и простой способ. Но здесь скрыта уязвимость: если вы попытаетесь создать два элемента одновременно, получите два одинаковых ID. Поэтому вместо поиска быстрых решений лучше довериться проверенным инструментам и способам.
😕 Вы могли заметить, что мы не упомянули хук useId. Дело в том, что такие идентификаторы будут уникальны только в рамках компонента, а нам нужны ID, которые уникальны глобально в рамках всего приложения.
Используя уникальные ключи в списках React, вы существенно оптимизируете работу приложения. Избегайте соблазна простого индексирования и дарите своим пользователям плавный и приятный опыт взаимодействия!
@chulakov_dev
Сегодня мы коснемся важной темы: как правильно использовать key при рендеринге списков в React.
🔑 Key — это специальный атрибут для эффективного сопоставления элементов при изменении списка (и не только, но сейчас не об этом). Он критически важен для оптимальной производительности.
Проще всего в качестве ключа указать индекс элемента в массиве, однако подобный подход равносилен полному отсутствию ключа. Иногда это не приводит к проблемам, например, если ваш функционал предусматривает только добавление нового элемента в конец или ваш список абсолютно статичен.
Однако вы рискуете столкнуться с трудноуловимыми багами и лишними перерендерами при сортировке, фильтрации или добавлении элементов в начало списка. Все дело в том, что без уникальных ключей React не сможет правильно сопоставить старую и новую версии вашего списка.
Используйте уникальные ID в качестве ключей. Если данные приходят с бэкенда, они, вероятно, уже имеют ID. На клиентской стороне вы можете указать сами уникальные идентификаторы или использовать библиотеку Nanoid для генерации, но делать это нужно не в момент рендера, а при определении массива. Кстати, по этой же причине и не рекомендуется применять метод Date.now().
Может показаться, что использовать Date.now() в качестве уникального ID — это быстрый и простой способ. Но здесь скрыта уязвимость: если вы попытаетесь создать два элемента одновременно, получите два одинаковых ID. Поэтому вместо поиска быстрых решений лучше довериться проверенным инструментам и способам.
Используя уникальные ключи в списках React, вы существенно оптимизируете работу приложения. Избегайте соблазна простого индексирования и дарите своим пользователям плавный и приятный опыт взаимодействия!
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17❤3👍1
👍10🔥7😢2
Привет!
В системе типов TypeScript есть группа, которая называется гомоморфной, т.е. типы, которые изменяют функциональность, сохраняя первоначальные свойства применяемой сущности. В этой группе есть четыре типа: Readonly, Partial, Required, Pick.
Readonly — добавляет каждому свойству/методу объекта модификатор readonly, т.е. делает их доступными только для чтения.
Partial добавляет всем свойствам/методам модификатор ?, делая их необязательными.
В системе типов TypeScript есть группа, которая называется гомоморфной, т.е. типы, которые изменяют функциональность, сохраняя первоначальные свойства применяемой сущности. В этой группе есть четыре типа: Readonly, Partial, Required, Pick.
Readonly — добавляет каждому свойству/методу объекта модификатор readonly, т.е. делает их доступными только для чтения.
type User = {
name?: string;
}
type ReadonlyUser = Readonly<User> // { readonly name?: string; }
const user: ReadonlyUser = {
name: 'Jack'
}
// Cannot assign to 'name' because it is a read-only property.
user.name = 'John'
Обратите внимание на знак вопроса у свойства name. Мы намеренно сделали его необязательным, но Readonly оставит его таковым, так как, являясь гомоморфным, он не изменяет остальные модификаторы.Partial добавляет всем свойствам/методам модификатор ?, делая их необязательными.
type User = {
readonly name: string;
age: number;
};
type OptionalUser = Partial<User>; // { readonly name?: string; age?: number; }
const user: OptionalUser = {}; // Ok!
Required противоположен Partial. Он превращает члены объекта в обязательные, удаляя модификатор ?.type User = {
readonly name?: string;
age?: number;
};
type RequiredUser = Required<User>; // { readonly name: string; age: number; }
/**
* Type '{}' is missing the following properties
* from type 'Required<User>': name, age
*/
const user: RequiredUser = {}
И последний — Pick. Фильтрует объектный тип по свойствам/методам и формирует из него новый тип. Если вы знаете, как работает тип Omit, то это противоположная ему процедура. Первый дженерик принимает в себя фильтруемый тип, а второй — перечисление свойств/методов, которые требуется отфильтровать (перечисляются через оператор | ):type User = {
readonly name: string;
age: number;
height: number;
};
// { readonly name: string; age: number; }
type PickUser = Pick<User, 'name' | 'age'>;
const user: PickUser = {
name: 'Jack'
}
// Cannot assign to 'name' because it is a read-only property.
user.name = 'John'👍16🔥5⚡2
Всем привет!
Недавно у нас был пост с инструкцией, как создать свой образ Strapi. Сегодня мы расскажем, как настроить окружение для его дальнейшего использования в Docker.
👉🏻 Читать инструкцию
@chulakov_dev
Недавно у нас был пост с инструкцией, как создать свой образ Strapi. Сегодня мы расскажем, как настроить окружение для его дальнейшего использования в Docker.
👉🏻 Читать инструкцию
@chulakov_dev
🔥12👍5❤4
Друзья, привет!
➡️ Сегодня поговорим про замечательную функцию от Next.js — Incremental Static Regeneration (ISR) — и про то, как ревалидировать данные на уровне страницы по таймеру. Тема актуальна для всех, кто использует версию Next.js >= 12.4.
ISR — это функциональность, которая позволяет динамически обновлять статические страницы после сборки проекта, не пересобирая весь сайт, что очень полезно при частом обновлении контента (новости, цены в каталоге и т.д.).
↪️ По сути, это комбинация из лучшего, что есть у SSR/RSC и SSG, которая работает следующим образом:
— при первом запросе к странице отдается кешированная версия из сборки;
— затем в фоновом режиме запускается повторная генерация страницы через вызов getStaticProps;
— если генерация прошла успешно, обновленная версия попадает в кеш;
— при ошибке продолжит отдаваться предыдущая версия из кеша;
— так достигается отказоустойчивость;
— кеширование происходит локально на сервере, на Vercel кеш глобальный и автоматически распределяется (об этом сегодня не будем говорить).
Управлять ISR можно так:
— частоту обновления задать через revalidate в секундах в getStaticProps;
— принудительно очистить кеш через API-метод revalidate;
— On-demand revalidation при обновлении данных.
@chulakov_dev
ISR — это функциональность, которая позволяет динамически обновлять статические страницы после сборки проекта, не пересобирая весь сайт, что очень полезно при частом обновлении контента (новости, цены в каталоге и т.д.).
— при первом запросе к странице отдается кешированная версия из сборки;
— затем в фоновом режиме запускается повторная генерация страницы через вызов getStaticProps;
— если генерация прошла успешно, обновленная версия попадает в кеш;
— при ошибке продолжит отдаваться предыдущая версия из кеша;
— так достигается отказоустойчивость;
— кеширование происходит локально на сервере, на Vercel кеш глобальный и автоматически распределяется (об этом сегодня не будем говорить).
Управлять ISR можно так:
— частоту обновления задать через revalidate в секундах в getStaticProps;
— принудительно очистить кеш через API-метод revalidate;
— On-demand revalidation при обновлении данных.
// пример использованияТаким образом, ISR позволяет оптимально сочетать скорость статической генерации и гибкость обновления данных. Рекомендуем для сайтов с часто меняющимся контентом!
export const getStaticProps = async () => {
return {
props,
revalidate: 10, // ревалидировать каждые 10 секунд
}
}
// On-demand
await res.revalidate('/some-page')
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17⚡4👍4
Всем привет!
В новой статье на Хабре мы разобрали основные особенности языка Kotlin. Рассмотрели такие важные аспекты, как безопасность работы с null-значениями, гибкость типизации с помощью Generics, возможности расширения функциональности с помощью extension-функций, inline-функции и многое другое.
А еще поделились ссылками на полезные материалы, которые пригодятся в изучении Kotlin.
➡️ Читайте и подписывайтесь на наш блог.
@chulakov_dev
В новой статье на Хабре мы разобрали основные особенности языка Kotlin. Рассмотрели такие важные аспекты, как безопасность работы с null-значениями, гибкость типизации с помощью Generics, возможности расширения функциональности с помощью extension-функций, inline-функции и многое другое.
А еще поделились ссылками на полезные материалы, которые пригодятся в изучении Kotlin.
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Kotlin: взгляд изнутри — преимущества, недостатки и особенности
Всем привет! На связи Сергей, Android-разработчик Студии Олега Чулакова на проектах Сбера. В этой статье мы углубимся в мир Kotlin, рассмотрим его основные преимущества, недостатки и особенности. Мы...
🔥12👍4❤3
Мы все долго ждали этого момента — выхода нового большого интервью Олега Чулакова.
Олег поделился первыми успехами Студии на международном рынке и планами на будущее. Рассказал про идеологию Студии, которая выделяет ее на фоне других агентств и почему все копируют Студию. Обсудили бизнес в Дубае и России, найм сотрудников и многое другое. Получилось интересно, честно и с юмором.
Кто еще не смотрел, держите ссылку на интервью. Приятного просмотра.
@chulakov_dev
Олег поделился первыми успехами Студии на международном рынке и планами на будущее. Рассказал про идеологию Студии, которая выделяет ее на фоне других агентств и почему все копируют Студию. Обсудили бизнес в Дубае и России, найм сотрудников и многое другое. Получилось интересно, честно и с юмором.
Кто еще не смотрел, держите ссылку на интервью. Приятного просмотра.
@chulakov_dev
YouTube
Олег Чулаков, Дубаи, миллионы, продукт.
00:00 Начало
00:35 Как и почему этот подкаст состоялся?
01:16 Про копирование сайта Chulakov
04:15 Про цвет
07:41 Про минимализм в цвете и стиле сайта
11:46 Про спорт
13:41 Правда ли, что в Дубае женщинам продавать сложнее чем мужчинам?
16:46 Почему выбрал…
00:35 Как и почему этот подкаст состоялся?
01:16 Про копирование сайта Chulakov
04:15 Про цвет
07:41 Про минимализм в цвете и стиле сайта
11:46 Про спорт
13:41 Правда ли, что в Дубае женщинам продавать сложнее чем мужчинам?
16:46 Почему выбрал…
🔥13⚡3🐳3❤2