Кодовая база
1.27K subscribers
16 photos
1 video
32 links
База во фронтенд разработке.

Написать в личку: https://t.iss.one/devmargooo
Download Telegram
Channel created
Forwarded from S0ER
Promise.race

Всем привет, на связи Марго @devmargooo и сегодня я расскажу вам про Promise.race.🏎 Promise.race принимает в качестве аргумента массив промисов и возвращает результат того промиса, который завершится первым. Значит ли это, что после завершения Promise.race можно просто забыть про те промисы, которые проиграли гонку? Оказывается, нет. В 2017 году была описана интересная утечка памяти в Promise.race https://github.com/nodejs/node/issues/17469#issuecomment-685216777. Эта утечка интересна не сама по себе (мне кажется, Promise.race не так часто используют), а тем, что она представляет собой очень показательный пример утечки памяти в js через замыкания. Рассмотрим следующие тезисы.

1. Промис сохраняет свой результат все время, которое он живет.
Некоторые разработчики считают, что если мы не используем результат, который вернул промис, то он освободит память сразу после того, как промис завершится. Это не так! Результат промиса сохраняется в его внутреннем свойстве result все время, пока живет (= ссылочно доступен) сам промис.

2. Также, если промис зарезолвился, это еще не значит, что данные внутри его функции-исполнителя (функция, которую передали в конструктор промиса) больше не удерживаются в памяти. Нет, они могут удерживаться в памяти, например, если внутри исполнителя был setTimeout.

3. Рассмотрим следующий код и попробуем память, когда из памяти будет удален “super string”.
    const resolveString = new Promise((resolve) => resolve("super string"));
const neverResolve = new Promise(() => {});
const promises = [resolveString, neverResolve];

const p = new Promise((resolve, reject) => {
for (const promise of promises) {
Promise.resolve(promise).then(resolve, reject);
}
});

В данном случае neverResolve завис в памяти, а с ним и весь родительский промис p. Результат промиса resolveString сохранился как внутренее свойство result объекта p. Если “super string” - это тяжелые данные, то мы получим существенную утечку памяти. По всей видимости, механизм утечки памяти в Promise.race аналогичен вышеизложенному.
🤡32👍2
Channel photo updated
Forwarded from S0ER
Разделение ответственности в UI компонентах

Привет, на связи @devmargooo и сегодня я хотела бы рассказать свои мысли насчет разделения ответственности в UI компонентах. В своей “Чистой архитектуре” Р. Мартин пишет, что принцип единственной ответственности (SRP) является следствием закона Конвея и определяет, что лучшей является такая структура программной системы, при котором каждый модуль может быть изменен только вследствие удовлетворения интересов одного единственного актора. На мой взгляд, при разработке библиотеки UI компонентов удобно использовать схожий принцип, который можно сформулировать следующим образом: каждая логическая зона UI может менять свое состояние вследствие изменения конфигурации одного и только одного компонента в коде. Под “логической зоной” я пониманию небольшой кусочек UI, который несет полезную нагрузку для пользователя и может находится в разных состояниях. Разберем на примере текстового инпута. В нем я выделяю следующие логические зоны: поле ввода (возможные состояния - пустое, непустое, задизабленное, с ошибкой), крестик возле инпута (возможные состояния - присутствует, отсутствует), иконка возле поля ввода, подпись под полем ввода. Библиотеки UI компонентов часто разрабатывают таким образом, что в них есть “самые базовые компоненты” (например, Input), и компоненты, которые построены на основе этих “самых базовых компонентов” (ErrorInput, LabelInput, IconInput etc) по принципу “матрешки”. Таким образом, нам нужно следить, чтобы в этой иерархии изменять состояние каждой логической зоны мог только компонент! Например, возможность рендера иконки рядом с полем ввода должен иметь только один компонент - или Input, или IconInput, и тд. Рассмотрим следующий пример реализации Input и ErrorInput на React:
interface InputProps {
value: string;
setValue: (newValue: string) => void;
icon?:string;
}

const Input = ({value, setValue, icon}:InputProps) => (
<div className="input">
{icon && <div className="icon">{icon}</div>}
<input type="text" value={value} onChange={(e) => setValue(e.target.value)}/>
</div>
)

interface ErrorInputProps extends InputProps {
is_error?: boolean;
}

const ErrorInput = (props:ErrorInputProps) => (
<div className="error_input">
{props.is_error && <div className="error_icon">X</div>}
<Input {...props}/>
</div>
)

При таком подходе возможна ситуация, когда в ErrorInput будут одновременно переданы пропсы is_error и icon и в одной и той же логической зоне иконки будет отрендерено сразу две иконки, одна поверх другой. Следовательно,важно следить за тем, чтобы логическую зону иконки мог изменять только один компонент - в нашем случае это компонент Input. В своей практике я видела достаточно много багов, попавших на продакшн вследствие нарушения этого принципа.
🤡21👍1🔥1
Forwarded from S0ER
Как решать литкод

Всем привет, на связи снова @devmargooo и сегодня мы поговорим с вами о задачках с литкода. В то время, когда многие говорят о том, стоит ли вообще программисту тратить свое ценное время на решение задачек, преступно мало, на мой скромный взгляд, говорят о том, а как же их все-таки решить, эти задачки? В мануалах с ютуба все просто: блоггер читает условие и дальше решение зреет в его голове само собой, но на практике у многих людей почему-то так не происходит, сколько бы они не сидели перед ноутбуком и не вглядывались в свеженаписанный function declaration. Итак, мой способ - это идти к общему правилу от частного случая, он же метод индукции. Для этого нужно искусственно сократить мощность множества поступающих на вход данных, короче говоря, решить задачу для одного частного случая, причем максимально простого. В вашей функции на вход подаются число? Пускай это будет число 1. Строки? Возьмите строку из одного символа. Двоичные матрицы? Возьмите матрицу из одного элемента, максимально простого. И затем решите задачу для этого элемента. Как правило, такое решение не составляет труда, а написанный код не похож на свой финальный вариант. Далее возьмите еще один частный случай и решите задачу для него. Подумайте, можно ли объединить первые два случая в общее правило? Решите задачу для еще одного-двух случаев, и в этом момент вы уже начнете замечать закономерности, которые приведут вас к общему правилу. Дальше берите на вход все новые и новые виды входных данных, для которых написанное правило не работает, и решайте задачу для них, до тех пор, пока для всех возможных видов данных ваша задача не будет решена.
🔥6🤡1