Метод вопросов и ответов для изучения Node.js (2)

Node.js внешний интерфейс
Метод вопросов и ответов для изучения Node.js (2)

В: Хорошо, давайте перейдем к Node.js, я помню, как в прошлый раз я говорил о «неблокирующем» и «управляемом событиями», что возбудило мое любопытство, но вылило на меня ведро холодной воды, эти два слова это немного высокого класса.

A: Не волнуйтесь, давайте сначала посмотрим на простую сцену:

Вы должны были использовать Renren.com, чтобы просматривать новости друзей, верно? Простой способ добиться этого — поддерживать длительный опрос между пользователем и сервером.

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

С точки зрения традиционных серверов (таких как Apache), каждый раз, когда новый пользователь подключается к вашему веб-сайту, ваш сервер должен открывать новое соединение, каждое соединение должно занимать поток, и большинство этих потоков простаивают (например, ожидание от друзей, чтобы опубликовать статус, проверка базы данных и т. д.), хотя они простаивают, но все равно занимают память, то есть, если пользователь достигает определенного масштаба, память сервера будет исчерпана и парализована .

Есть много решений, например использование пула потоков, но он все равно заблокирован.Если все потоки в пуле потоков заблокированы (медленная скорость сети, временно используется кем-то злонамеренно), то следующий запрос будет в очереди.

Node.js отличается от других: он использует «неблокирующую» и «управляемую событиями» модель. Вы можете думать о нем как о цикле событий, который работает вечно. Когда приходит новый запрос, Event Loop получает этот запрос, а затем передает его другим потокам, таким как запрос к базе данных, а затем ответ на обратный вызов, а затем получение других запросов, вместо того, чтобы ждать возврата результата базы данных.

Если база данных возвращает результат, сервер возвращает его клиенту, и цикл продолжается. ЭтоСобытие: сервер будет иметь соответствующую обработку (или прием запросов, или некоторые обратные вызовы) только тогда, когда что-то произойдет.

В: Значит, неблокирующий и управляемый событиями Node.js основан на этом цикле событий?

A: Да, проще говоря, цикл событий Node.js основан на libuv, а цикл событий браузера основан наспецификация html5Конкретная реализация, определенная в , остается на усмотрение производителя браузера.

В: Интересно, есть два вида циклов событий.

A: Для сравнения, они чем-то похожи:

В браузере это относительно просто, стоит отметить, что после каждой задачи будут выполняться задачи в текущей очереди микрозадачи:

Node.js немного сложнее, каждый Event Loop должен пройти шесть этапов, после каждого этапа выполняется nextTick, микрозадачи (разрешенные промисы и т.д.):

   ┌───────────────────────┐
┌─>│        timers         │ <─── setTimeout/setInterval callback
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
│             │                   │ microTask queue         │
│  ┌──────────┴────────────┐      └─────────────────────────┘
│  │     I/O callbacks     │
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
│             │                   │ microTask queue         │
│  ┌──────────┴────────────┐      └─────────────────────────┘
│  │     idle, prepare     │ <─── 仅内部使用
│  └──────────┬────────────┘
│             │                   ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <──────────────── │                         │
│             │                   │ microTask queue         │
│             │                   └─────────────────────────┘
│             │                   ┌─────────────────────────┐
│  ┌──────────┴────────────┐      │      incoming:          │
│  │         poll          │ <────┤      connections,       │
│  └──────────┬────────────┘      │      data, etc          │
│             │                   └─────────────────────────┘
│             │                   ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <──────────────── │                         │
│             │                   │ microTask queue         │
│             │                   └─────────────────────────┘
│  ┌──────────┴────────────┐
│  │        check          │ <─── setImmediate callback
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
│             │                   │ microTask queue         │
│  ┌──────────┴────────────┐      └─────────────────────────┘
│  │    close callbacks    │ <─── eg: socket.on("close",func)
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
└─────────────┴                   │ microTask queue         │
                                  └─────────────────────────┘

Давайте возьмем простой код и угадаем, что выводят браузер (Chrome) и Node.js соответственно:

console.log('start');

setTimeout(() => {
  console.log('timer1');
  Promise.resolve().then(() => {
      console.log('promise1');
  });
}, 0);

setTimeout(() => {
  console.log('timer2');
  Promise.resolve().then(() => {
    console.log('promise2');
  });
}, 0);

console.log('end');

В: Браузер (Chrome) должен выводить start, end, time1, promise1, time2, promise2 Что касается Node.js, я думаю, то же самое?

A: Давайте сначала проверим:

В браузере:

start
end
timer1
promise1
timer2
promise2

В Node.js:

start
end
timer1
timer2
promise1
promise2

Кажется, это отличается от того, что вы себе представляли, не волнуйтесь, просто посмотрите на анимацию, и вы поймете:

В браузере:

В Node.js:

В: Оказалось, что если каждыйsetTimeout callbackплюсprocess.nextTickтогда чемPromise.thenВыполнить первым?

A: Да, помните, что я сказал выше, очередь nextTick и очередь micktasks будут выполняться после каждого этапа, и приоритет очереди nextTick выше, чем у очереди miktasks.

В: Я понимаю. Кстати, я помню, вы упомянули либув, что это такое? Разве там не сказано, что Node.js использует v8, какое это имеет отношение к v8?

А:...

Продолжение следует...

Примечание. После версии Node v11+ результат работы такой же, как и в браузере.

разное

Ссылаться на