Задать вопрос
  • Почему именно такой порядок вывода в консоль?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Исследования в первоначальной версии ответа (ниже) натолкнули на поведение, которое смог объяснить Jonas Wilms в ответе на SO.

    Возврат промиса из C1 then() создаёт ТРИ последовательных микротаска:
    1. NewPromiseResolveThenableJob, который вызывает then() на том уже отресолвленном промисе, что вернули в C1. И т.к. этот промис уже отресолвлен, сразу же в очередь вставляется следующий микротаск:
    2. NewPromiseReactionJob этого уже разрешенного промиса, и этот, в свою очередь, добавляет третью микрозадачу:
    3. ещё одну NewPromiseReactionJob, которая уже выводит в лог "2".


    Если возвращать не промис (и не thenable объект), а "простое" значение или undefined, то добавляется всего один микротаск.

    Раньше подобная задержка в три шага была и для await, но потом её оптимизировали в движке V8. А вот про then() забыли.

    Подробнее стоит посмотреть ответ на SO, ссылка в начале.

    [первая версия ответа]

    Интересный вопрос! Больше экспериментов.
    Вспомогательная функция для читаемости:
    const log = (value, returnPromise) => () => {
      console.log(value);
      if (returnPromise) return Promise.resolve();
    };
    Возвращает функцию, которая обычный console.log() с переданным значением. И если второй аргумент трушный, то вернёт отрезолвленный промис.

    Эксперимент 1. «Застёжка-молния»
    Promise.resolve()
      .then(log('a1'))
      .then(log('a2'))
      .then(log('a3'))
      .then(log('a4'))
      .then(log('a5'))
      .then(log('a6'))
    ;
    
    Promise.resolve()
      .then(log('b1'))
      .then(log('b2'))
      .then(log('b3'))
      .then(log('b4'))
      .then(log('b5'))
      .then(log('b6'))
    ;
    Выводит поочередные a1 b1 a2 b2 a3 b3 ...
    Эксперимент 2. «Отстаём на 2»

    Единственное отличие: в первом А возвращаем отресолвленный промис.
    Promise.resolve()
      .then(log('a1', true))
      .then(log('a2'))
      .then(log('a3'))
      .then(log('a4'))
      .then(log('a5'))
      .then(log('a6'))
    ;
    
    Promise.resolve()
      .then(log('b1'))
      .then(log('b2'))
      .then(log('b3'))
      .then(log('b4'))
      .then(log('b5'))
      .then(log('b6'))
    ;

    Выводит
    a1 b1 b2 b3 a2 b4 a3 b5 a4 b6 a5 a6
    А-шки после 1-й отстают на 2, пропустив вперёд b2 и b3.

    Очередь микрозадач работает как FIFO буфер: первый пришёл, первый ушёл.

    Цепочка из then() выполняется асинхронно. После выполнения очередного, создаётся следующий microtask. Несколько цепочек, как видно из 1-го эксперимента, выполняются параллельно-пошагово, «молнией».

    Возврат созданного выполненного промиса, и ожидание его разрешения вызывает задержку в очереди микрозадач на 1 микротаск + «перемещение» цепочки "А" в конец (меняется порядок a-b => b-a):
    "молния"
    a1 b1 ; a2 b2 ; a3 b3 ; a4 b4 ; a5 b5 ; a6 b6
    
    с промисом в А1
    a1 b1 ; b2 ; b3 a2 ; b4 a3 ; b5 a4 ; b6 a5 ; a6


    Подробнее с тремя цепочками

    На этот раз три цепочки промисов "a", "b", "c". Цепочка "А" вернёт промис на 1-м шаге, "С" — на 4-м. Код эксперимента:
    const output = [];
    
    const makeChain = (key, n = 5, trueStep = false) => {
      let p = Promise.resolve();
      const arrow = isArrow => isArrow ? '->' : '';
      for (let i = 1; i <= n; i++) {
        const returnPromise = trueStep === i;
        const afterPromise = trueStep === i - 1;
        p = p.then(() => {
          output.push(`${arrow(afterPromise)}${key}${i}${arrow(returnPromise)}`);
          if (returnPromise) return Promise.resolve();      
        });
      }
      return p.catch(console.error);
    };
    
    const n = 7;
    makeChain('a', n, 1),
    makeChain('b', n),
    makeChain('c', n, 4),
    
    // мАкрозадача выполнится после всех мИкрозадач:
    setTimeout(() => console.log(output.join(' ')));

    Результат c вручную добавленными разбивками:
    a1-> b1 c1 ; b2 c2 ; b3 c3 ->a2 ; b4 c4-> a3 ; b5 a4 ; b6 a5 ; b7 ->c5 a6 c6 ; a7 c7
    Тут всё ещё не вполне мне понятен порядок после возврата промиса из C4.
    Ответ написан
  • Где лучше инициализировать state manager, и нужно ли это вообще?

    @SouLFiX
    На реакте у тебя не странички, это компоненты. Стоп инициализируется обычно отдельно от реакта. Это если вкратце.

    Такие абстрактные вопросы лучше у chatgpt4 спрашивать.
    Ответ написан
    Комментировать
  • Какой вид веб-сервера выбрать в Certbot?

    SignFinder
    @SignFinder
    Wintel\Unix Engineer\DevOps
    Nginx или haproxy

    P.S. Нужно уметь их устанавливать и настраивать.

    P.P.S. "Software" - это не пункт для выбора, а заголовок поля выбора.
    Ответ написан
    Комментировать
  • Какой вид веб-сервера выбрать в Certbot?

    Steel_Balls
    @Steel_Balls
    Лучше и проще всего Nginx.
    При возникновении проблем огромное сообщество поможет их решить
    Ответ написан
    Комментировать
  • Делается ли merge при rebase?

    toxa82
    @toxa82
    Итоговый результат слияния кода при merge и rebase одинаковый. Разница будет только в порядке коммитов в истории. Merge сверху применяет новые коммиты, rebase находит общего предка, убирает ваши новые коммиты в ветке, обновляет ветку, применяет ваши новые коммиты сверху.
    Ответ написан
    Комментировать
  • Можно ли оставить then() пустым?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Это плохая установка по умолчанию. я ее всегда выключаю.

    Вы тоже можете выключить, или заглушить комментарием в коде

    // noinspection JSIgnoredPromiseFromCall
    fn();


    Настройка этой инспекции здесь
    63186024a02db109547962.png
    Ответ написан
    Комментировать
  • Какая есть альтернативу шрифту outfit?

    @lekras
    Полный аналог с кириллицей вряд ли найдется.
    По пропорциям близок Circe, но он не бесплатный
    Ответ написан
    Комментировать
  • Что такое slug в разработке?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Чаще всего, как уже написали, встречается в URL, но все же его значение чуть более шире - slug это уникальная строка идентификатор, понятная человеку (в отличие от ID) и содержащая только "безопасные" символы:
    - 0-9
    - a-z (общепринято - в нижнем регистре)
    - символ -
    - иногда еще символ _
    Могут использоваться не только в URL для понятности, но и, например, в запросах к БД (в первую очередь - на уровне АПИ) - ведь
    SELECT * FROM pages WHERE category="some-slug"
    более понятно, чем
    SELECT * FROM pages WHERE category=126.
    На уровне API это выглядит как
    get_pages_in_category( 'some-slug' )
    или
    $object->get_pages_in_category( 'some-slug' ).
    В общем, это человеко-понятный уникальный идентификатор.
    Ответ написан
    1 комментарий
  • Плох ли tailwind?

    Fragster
    @Fragster
    помогло? отметь решением!
    Замедляет ли tailwind работу сайта в продакшене?
    нет или незначительно. количество классов у элемента почти не влияет на скорость отрисовки. но атомарные классы при этом положительно влияют на размер файла стиля. Очень жду, когда появится анализатор по аналогии с https://windicss.org/features/analyzer.html , чтобы повторы/незначительные вариации стилей проанализировать и перенести arbitrary values в конфиг.

    Или он нужен только на этапе разработки?
    не понятно (

    Стоит ли использовать tailwind в крупных проектах, если нет, то почему. И что стоит использовать?
    Стоит. Единственное, нужно фирменные элементы стиля зафиксировать в конфиге tailwind, можно вообще отказаться от дефолтного конфига и сделать свой с нуля.

    И что стоит использовать?
    Ну вот вышеупомянутый windy - почти то же самое, что tailwind, но со своими плюсами (группировка классов - бомба, анализатор тоже полезная вещь) и минусами, например не 100% совместимость с tailwind и некоторые (некритичные) глюки в вычисляемых классах vue). Просто tailwind более распространен.
    Ответ написан
    Комментировать
  • "localstorage" или cookie?

    Ivanq
    @Ivanq
    Знаю php, js, html, css
    Плюсы:
    localStorage отключить нельзя.
    localStorage будет жить вечно, если только вы или пользователь не удалите (или комп не сгорит ) ).
    Использовать localStorage проще
    document.cookie = "a=b"; // Добавляем куки
    document.cookie = "a="; // Удаляем куки
    // ??? Скачиваем функцию для получения куки
    
    localStorage.addItem("a", "b");
    localStorage.removeItem("a");
    localStorage.getItem("a");
    // или
    localStorage.a;


    Минусы:
    Работает как cookie, только с сервера ставить нельзя.
    Для получение с сервака нужно в запросе передавать.
    Ответ написан
    2 комментария
  • Как правильно обрабатывать события в node-telegram-bot-api?

    mak_ufo
    @mak_ufo
    Кратко:
    Возьмите telegraf и посмотрите этот раздел

    Более развёрнуто:
    Вам нужно где-то хранить "состояние" пользователя. Например, в БД или Redis. И тогда код будет примерно такой:
    bot.on('message', msg => {
         const session = getSessionFromDb(msg.from.id)
         if (session === 'foo') { //пользователь уже ввёл напоминание
             //обрабатываем одним способом
         } else if (session === 'bar') { //пользователь не ввёл 
            //обрабатываем другим способом
         }
    })


    Развёрнуто:
    Читайте про конечную машину состояний. Её суть в том, что она на одинаковые входные данные возвращает разные значения в зависимости от состояния, в которой она находится. В той же википедии это подробно описано.
    Ответ написан
    1 комментарий