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

    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.
    Ответ написан
  • Как скрыть ключ апи от пользователя?

    opium
    @opium
    Просто люблю качественно работать
    Проксируйте все запросы через себя и у себя подсовывайте апи ключ
    Ответ написан
    Комментировать
  • Какой выбрать роутер для обхода блокировок?

    @mltk
    Есть почти специальный роутер :) для обхода блокировок -- Routerich

    Там сразу OpenWRT в дружелюбном обличии, есть даже мастер настройки как на каких-нибудь длинках.
    Все возможные пакеты, которые могу понадобиться для обхода уже установлены.

    Включить обход блокировок -- скопипастить одну команду.

    Но самое главное -- это поддержка и комьюнити -- t.me/routerich

    Купить можно на озоне или по предзаказу в телеграме по ссылке выше с бесплатной доставкой в ближайший СДЭК.

    P.S. технически это аналог роутера Xiaomi AX3000T, только в Роутерич в добавок есть ещё порт USB 2.0 -- можно воткнуть LTE-модем и т.п. Цены смотрите сами, на мой взгляд это оправданная доплата за USB, отсутствие необходимости что-то прошивать/выбирать правильную прошиваемую ревизию железа Сяоми, а так же за поддержку/комьюнити в телеге.
    Ответ написан
    Комментировать