• Как подойти к тестированию функции-преобразователя?

    alexiusp
    @alexiusp
    senior frontend developer
    Зависит от деталей, но в общем случае - первый вариант, да. Нужно замокать входные данные, замокать ожидаемые выходные и так тестировать. Но это не значит, что более мелкие внутренние функции тестировать не нужно.
    Ответ написан
    Комментировать
  • Как выполнять функцию через динамичные промежутки времени?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const func = () => {
      console.log('hello, world!!');
      setTimeout(func, 500 + Math.random() * 1000 | 0);
    };
    
    func();
    Ответ написан
    7 комментариев
  • Как разобраться в битовых масках или как их там?

    sergiks
    @sergiks Куратор тега ВКонтакте
    ♬♬
    Про двоичное представление чисел вы же в курсе?
    0 = 0000 0000
    1 = 0000 0001
    2 = 0000 0010
    3 = 0000 0011
    4 = 0000 0100
    5 = 0000 0101
    6 = 0000 0110
    7 = 0000 0111
    8 = 0000 1000
    9 = 0000 1001

    ... и так далее. До 232 или даже до 264 - зависит от системы, 32- или 64-битной и языка программирования.

    Позиции битов считаются справа налево. Крайний правый бит имеет позицию 0. Позиция бита – это степень двойки. Если бит установлен в 1, надо прибавить 2 в степени этой позиции.

    Например, число 3 = 0000 0011 означает 20 + 21 = 1 + 2 = 3.

    Примечательно, что степени двойки – 0, 1, 2, 4, 8, 16, 32, 64, ... – выражаются всего одним включённым битом, одной единичкой, остальные биты – нули.

    Битовые маски – это договорённость, что каждый бит (каждая позиция) значит что-то определённое, что может быть включено или выключено, 1 или 0. Как линейка выключателей.

    Например, с разрешениями ВКонтакте:
    1 - бит 0 - notify
    2 - бит 1 - friends
    4 - бит 2 - photos
    8 - бит 3 - audio

    У ВК линейка длинная, состоит из 32 «выключателей».

    Допустим, вашему приложению требуются разрешения photos и audio – биты 2 и 3 надо установить в 1, остальные 0. Это можно сделать простым сложением: 22 + 23 = 4+8 = 12. В двоичной системе: 12 = 0000 0000 0000 1100

    Для удобства вычисления ВК прямо пишут значения, которые надо прибавить, чтобы получить нужную битовую маску – итоговое число, которое вы передадите в метод АПИ для запроса разрешения.

    Ещё один пример, вам требуется стена wall и offline доступ в любое время. Смотрите в таблице, какие там числа: wall (+8192) и offline (+65536). Значит, вам нужно просить разрешения для маски 73728
    Ответ написан
    Комментировать
  • Как правильно использовать интерцепторы в axios?

    owl1n
    @owl1n
    fullstack developer
    Покажу немного практик, как интерцепторы упрощают жизнь мне, да и многим, в целом.
    Здесь и далее покажу именно использование интерцепторов при работе с авторизацией по JWT (токены).

    1) Подстановка хедера авторизации

    const createSetAuthInterceptor = options => config => {
      if (options.access) {
        config.headers.Authorization = options.access;
      } else {
        delete config.headers.Authorization;
      }
      return config;
    };
    
    const setAuthCb = createSetAuthInterceptor(store.state.auth);
    axios.interceptors.request.use(setAuthCb);


    Здесь мы проверям наличие доступа из стора, а точнее, наличие токена. Далее, подставляем, либо удаляем заголовок.

    2) Следующая практика, это обновление токена (то, о чем вы спросили в комментарии, при окончании сессии и т.д.)

    let refreshTokenPromise;
    
    const createUpdateAuthInterceptor = (store, http) => async error => {
      const message = get(error, 'response.data.message');
      if (!['Token expired', 'Invalid token'].includes(message)) {
        return Promise.reject(error);
      }
    
      if (!refreshTokenPromise) {
        refreshTokenPromise = store.dispatch('refreshToken');
      }
    
      await refreshTokenPromise;
      refreshTokenPromise = null;
    
      return http(error.config);
    };
    
    const updateAuthCb = createUpdateAuthInterceptor(store, axios);
    axios.interceptors.response.use(null, updateAuthCb);


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

    В этом же решение, вместо обновления токена, можно отправлять юзера авторизовываться самому, на страницу авторизации. Для этого, конечно же, стоит передавать не экземпляр store, а экземляр роутера, чтобы редиректить юзера. Надеюсь, помог и хоть как то наглядно показал способы применения :)
    Ответ написан
    1 комментарий
  • Как решить задачу без применения if switch?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Надо сделать объект - ключами будут языки, значениями массивы дней недели:

    const getDayName = (day, lang) => (({
      en: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
      ru: [ 'Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота' ],
    })[lang] || [])[day - (7 * Math.floor(day / 7))];
    
    
    getDayName(5, 'en') // 'Friday'
    getDayName(7, 'ru') // 'Воскресенье'
    getDayName(-19, 'ru') // 'Вторник'
    getDayName(4, 'fr') // undefined

    А вообще, можно обойтись и без вспомогательной структуры данных:

    const getDayName = (day, lang) =>
      new Date(2001, 0, ((day % 7) + 7) % 7).toLocaleString(lang, { weekday: 'long' });
    
    
    getDayName(4, 'fr') // 'jeudi'
    getDayName(36, 'de') // 'Montag'
    Ответ написан
    Комментировать
  • Как перестать говнокодить и принимать неверные архитектурные решения?

    miraage
    @miraage
    Старый прогер
    как писать поддерживаемый код?

    Если уж очень коротко, то соблюдать SOLID/GRASP. Мне понравился твит одного из авторов React Router:
    https://twitter.com/mjackson/status/1171524189850701825

    Most common mistake software developers make: putting stuff in the wrong place. Coupling responsibilities and concepts that should be kept separate.
    For me, this is 95% of software development. Just figuring out *where* things belong.


    Что гуглить, что учить?

    Фундаментальные знания, вроде вышеупомянутых SOLID/GRASP, паттерны (не только классические паттерны, но и вообще, общеизвестные решения определённых задач), базовые структуры данных. Фреймворки/библиотеки всегда будут приходить/уходить, что-то будет забываться. А фундаментальные знания всегда актуальны.

    Может литературу какую почитать посоветуете?

    Скажу за себя. Ни одной из этих известных книжек за свою жизнь не прочитал. Писал много говнокода дома, очень много. Удалял, переписывал. Смотрел код других людей, анализировал, пытался перенять то, что считал правильным.

    Можно ли себя называть миддлом, если твой код говно?

    Не пытайтесь себя оценить. В каждой компании свои понятия миддла. А если кто-то 35 лет на лиспе кодил, а потом прыгнет на Angular - кто он, джун или сеньор?
    И, да, все мы в какой-то степени пишем говнокод. Если кто-то Вам доказывает, что он пишет супер чистый код - не слушайте.

    И ответ на главный вопрос.
    Как перестать говнокодить и принимать неверные архитектурные решения?

    Это невозможно. Все проекты, которые чуток сложнее CRUD-ов, рано или поздно обрастают говнокодом. Никто не пишет идеальный код. Код должен работать и решать проблемы бизнеса.
    Ответ написан
    6 комментариев
  • Кто может проверить грамотность кода?

    0xD34F
    @0xD34F Куратор тега JavaScript
    как улучшить мой код

    Подобный код не улучшают, а переписывают.

    function fearNotLetter(str) {
      const missing = Array
        .from(str, n => n.charCodeAt(0))
        .find((n, i, a) => n !== a[0] + i);
    
      return missing && String.fromCharCode(missing - 1);
    }
    Ответ написан
    4 комментария
  • Чем руководствоваться при выборе, вынести ли "подкомпонент" react в компонент или поместить в функцию внутри компонента?

    DarthJS
    @DarthJS
    Повторяющиеся блоки лучше выносить в отдельные компоненты, их не только можно переиспользовать, но и есть ряд удобств.

    Причины почему не стоит возвращать компоненты из методов класса:
    1) Метод должен выполнять какое-то действие, а не возвращать компонент. В большом приложении вам этот подход очень упростит работу.
    2) При тестировании проще тестировать маленький отдельный компонент, нежели тестировать большой компонент, еще и его методы, которые возвращают тоже компоненты.
    3) Используя Реакт девтул для хрома вам будет намного проще дебажить отдельные компоненты и смотреть полную иерархию вашего приложения, просматривать и изменять стейты и пропсы, чем при использовании методов класса. (Просто проверьте это и будет вопросы отпадут).
    4) Если выносить блоки в отдельные компоненты, ваши файлы с текущими компонентами будут намного меньше, удобней будет читать код, и, в зависимости от вашей IDE, всегда сможете узнать что внутри компонента, наведя на него, а не скролить большой класс с методами, в которых хранятся блоки либо списки с какими-то вычислениями, что может быть еще хуже.

    Ответ написан
    Комментировать
  • Чем руководствоваться при выборе, вынести ли "подкомпонент" react в компонент или поместить в функцию внутри компонента?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    вопросов о выносе SubmitButton в отдельный компонент не возникает.

    SubmitButton выносить в отдельный компонент не надо. В большинстве случаев хватает использования обычной кнопки вашего приложения.
    <Button onClick={handleSubmit}>Submit</Button>

    Чем руководствоваться при выборе, вынести ли «подкомпонент» react в компонент или поместить в функцию внутри компонента?


    Компонент это сущность, если часть древа можно описать как сущность, то логичней ее вынести в компонент. Особенно если она будет в последствии переиспользована. Например:
    ListItem, Preloader, Layout, Modal, Container, FormControl, etc.

    Если часть древа описывается задачей(например renderRows, renderItem, etc) и ее надо меморизировать, или она используется под условным рендерингом и для отрисовки необходимы дополнительные вычисления, то ее часто логично вынести в отдельный рендер метод, не нагромождая кодовую базу дополнительными компонентами.
    Колбеки паттерна render-props так же имеет смысл выносить в отдельные render-методы.
    Ответ написан
    1 комментарий
  • Как упростить данный код?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сделать объект, где ключами и значениями будут возможные значения stage и соответствующие им значения, передаваемые в emit первым параметром:

    const STAGES = {
      2: 'itemGv',
      5: 'itemTm',
    };

    После этого множество условных операторов внутри цикла можно заменить на один - извлекаем из объекта значение, проверяем, что оно не мусор:

    for (const [ key, val ] of Object.entries(items)) {
      const s = STAGES[val.stage];
      if (s) {
        this.client.srem('items', key);
        this.emit(s, val);
      }
    }
    Ответ написан
    Комментировать
  • Как просуммировать значения отмеченных чекбоксов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Где элементы находятся, что за элементы, как просуммировать, что сделать с суммой:

    const container = document;
    const selector = 'input[type="checkbox"]';
    const sumElements = elements =>
      Array.prototype.reduce.call(elements, (acc, n) => acc + +n.value, 0);
    const onSumChange = sum => console.log(sum);

    Полный пересчёт суммы при любых изменениях + делегирование:

    container.addEventListener('change', function({ target: t }) {
      if (t.matches(selector)) {
        onSumChange(sumElements(this.querySelectorAll(`${selector}:checked`)));
      }
    });
    
    container.querySelector(selector).dispatchEvent(new Event('change', { bubbles: true }));

    Или, исправление суммы с учётом конкретного чекбокса, изменившего своё состояние + обработчик события цепляется к каждому чекбоксу индивидуально:

    const cb = container.querySelectorAll(selector);
    let sum = sumElements(Array.prototype.filter.call(cb, n => n.checked));
    const onChange = e => onSumChange(sum += e.target.value * [ -1, 1 ][+e.target.checked]);
    cb.forEach(n => n.addEventListener('change', onChange));
    onSumChange(sum);
    Ответ написан
    3 комментария
  • Рынок digital-услуг переполнен?

    Anitamsk
    @Anitamsk
    Frontend Dev
    Вы правы, рынок очень переполнен, переполнен второсортными специалистами которые не хотят развиваться, но в тоже время просят огромную зп за свои soft скилы, в нашей компании месяц вели поиск человека на должность бэкендера Node.js, рекрутеры просто поседели от уровня тупизны которую хвостом тянут за собой "специалисты"
    Ответ написан
    22 комментария
  • Трудоустройство в IT сфере, обязательное высшее образование?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Обязательно умение пользоваться поиском. Этот вопрос задают на Тостере еженедельно.

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

    Бумажки никому не интересны, кроме ежегодно уменьшающегося процента компаний с жёсткой кадровой политикой. Да и таким компаниям ваш диплом не нужен, они просто поставят галочку "имеет ВО" в личном деле и подошьют скан диплома, даже не заглянув в него.

    И что уж говорить о европейских странах, Норвегии, США и т.д? Получить там работу без вышки ты попросту не сможешь, каким бы ты невероятно талантливым и умелым не был.

    Вы ошибаетесь. Во многих странах диплом заменяется пятью годами профильного стажа. И опять же, ежегодно Запад ослабляет требования к кандидатам, так как у них темпы роста кадрового голода ещё больше, чем в РФ. Если раньше хантили только топовых сеньоров, то сейчас уже готовы брать на себя расходы по релокации даже для мидлов.
    Ответ написан
    9 комментариев
  • Как работает этот код с axios?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Я вам это пример тогда скинул, чтобы показать приближенный к жизни кейс использования этого компонента. Все совсем не обязательно должно быть реализовано именно так.

    1. Смотрите у вас компонент реализует бесконечную подгрузку информации с сервера. Но как вы собрались реализовывать взаимодействие клиента и сервера? Как серверу узнать сколько данных вы получили и какие отдавать дальше? Простейший и проверенный временем вариант пагинация. Надо использовать пагинатор на стороне сервера.
    Допустим на сервере 500 изображений. Как запросить первые 20?
    GET 'api/images?limit=20&page=1'
    Сервер должен вернуть что-то вроде:
    {
      data: [...],
      quantity: 500,
    }

    Теперь вы знаете, что изображений всего 500.
    Запрос на следующие 20 изображений будет:
    GET 'api/images?limit=20&page=2'

    Как только вы загрузите 25-ую страницу, условие в render:
    const hasMore = page * limit < total;
    вернет false, так как:
    25 * 20 < 500 // false
    И ваш компонент перестанет обращаться к серверу и показывать прелоадер при прокрутке в конец списка, так как он полностью загружен.
    Как-то так. Клиент видит бесконечный список, а по факту сервер возвращает данные постранично.

    2. spread operator
    https://developer.mozilla.org/ru/docs/Web/JavaScri...
    es6-features.org/#SpreadOperator
    jsraccoon.ru/es6-spread-rest
    const arr1 = ['a'];
    const arr2 = ['b'];
    const arr3 = [...arr1, ...arr2];
    const arr4 = [...arr1, 1, ...arr2, 'c'];
    
    console.log(arr3); 
    // => ['a', 'b'];
    
    console.log(arr4); 
    // => ['a', 1, 'b', 'c'];
    
    const obj1 = { a: 'a', b: 'old b' };
    const obj2 = { b: 'new b', c: 'c' };
    const obj3 =  { ...obj1, ...obj2 };
    const obj4 = { ...obj2, ...obj1 };
    const obj5 =  { ...obj1, ...obj2, d: 'd' };
    
    console.log(obj3);
    // => { a: 'a', b: 'new b', c: 'c' };
    
    console.log(obj4);
    // => { a: 'a', b: 'old b', c: 'c' };
    
    console.log(obj5);
    // => { a: 'a', b: 'new b', c: 'c', d: 'd' };


    3. Хорошо изучить JavaScript, можно пройти уроки на learn.javascript.ru. Изучайте пути решения типовых задач веба: валидация, авторизация, пагинация, CRUD, REST, передача и хранение файлов и прочее. И пробуйте это на практике.
    Ответ написан
    Комментировать
  • Как правильно заменить / добавить элемент массива?

    0xD34F
    @0xD34F
    Если items это массив TCardItem, то и передавать в saveItem и addItem наверное надо TCardItem, а не object:

    saveItem = (id: string, modifiedItem: TCardItem) => {

    Кстати, а зачем в saveItem отдельно передавать id? - он же должен быть в modifiedItem.
    Ответ написан
    1 комментарий
  • Какие области в веб - разработке осваивать в перспективе?

    dom1n1k
    @dom1n1k
    В общем у меня уйдёт на это 2 - 2.5 месяца. Только на основы!

    Ну обосраться. Два грёбаных месяца!!!1
    До чего докатилась индустрия, что 2 месяца воспринимаются как огромный срок. И всё чаще натыкаешься на статьи, где пишут о годовалых якобы мидлах и трехлетних якобы сеньорах.
    Лично я считаю, нужно потратить от 2-3 лет, чтобы начать более-менее прилично и системно ориентироваться в теме. В течении этих лет неоднократно будут возникать моменты, когда тебе кажется, что ты уже достаточно крут - но это только кажется.
    Нормальный специалист средней руки формируется около 3 лет. Не гуру, не сенсей, не сеньор - просто крепкий линейный боец. Это много где так, не обязательно в JS. И это нормально.
    Хочешь за несколько недель - иди установщиком пластиковых окон, как раз строительный сезон начался.
    Ответ написан
    11 комментариев
  • Как запустить рендер компонентов из MobX map react?

    0xD34F
    @0xD34F Куратор тега React
    modals.entries() судя по документации должен предоставить [key, value]

    Нет, не должен. Он итератор возвращает, а не массив. Так что

    [...modals.entries()].map(([ id, modal ]) => (
    
    ))
    Ответ написан
    1 комментарий
  • Как удачнее реализовать редактирование карточек?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    ElemInput - бесполезная обертка с понятным только вам интерфейсом, усложняющая код.
    Старайтесь так никогда не писать. Если описываете интерфейс, используйте традиционные имена свойств для компонентов(name, onChange etc).
    Посмотрите хороший пример по работе с формами из официальной документации.
    Ответ написан
    Комментировать
  • Как начертить линии с помощью html/css?

    webinar
    @webinar
    Учим yii: https://youtu.be/-WRMlGHLgRg
    Обычно используют canvas или svg для подобного. В частности можно использовать библиотеки, которых не мало, например:
    https://threejs.org
    https://svgjs.com
    paperjs.org
    pablojs.com
    и еще 100500 вариантов
    Ответ написан
    Комментировать
  • Как экспортировать 3D-модель из 3DMax в CANVAS?

    svaa1982
    @svaa1982
    Web разработчик с трёхмерным уклоном
    Используйте плагин Verge3D для 3ds Max
    Ответ написан
    Комментировать