Node JS SetTimeOut обратный вызов

Я проходил обучение node JS на канале newboston (ссылка https://thewikihow.com/video_KsjrN-T3ZCs). и Пример того, как Node обеспечивает лучшую производительность, показан ниже.

function placeAnOrder(orderNumber) {
    console.info("Order placed", orderNumber);
    cookAndDeliver(function () {
        console.info("Delivered order", orderNumber);
    });
};


function cookAndDeliver(callback){
    setTimeout(callback, 5000);
};


placeAnOrder(1);
placeAnOrder(11);
placeAnOrder(111);
placeAnOrder(1111);
placeAnOrder(11111);

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

Объяснение, данное видео, заключалось в том, что обратный вызов не является препятствием, и код будет выполняться без прерывания, с чем я согласен, но я не понимаю, почему узел не соблюдает значение тайм-аута?

Я предполагаю, что, поскольку он работает в асинхронном режиме, это означает, что отдельный поток будет обрабатывать каждый вызов, верно ли мое предположение?

is my assumption correct Нет, все, что вы сделали, это установили таймаут на 5 секунд для всего, так что через 5 секунд все произойдет. Вы не создали цепочку setTimeout's ..
Keith 30.05.2018 02:18

@Keith Поскольку я пришел из фона java, я понимаю, что либо выполнение будет синхронным, тогда каждый вызов функции будет происходить после другого, либо выполнение будет асинхронным, поэтому каждый вызов будет выполняться в отдельном потоке, а затем все могут закончите аналогично тому, что было объяснено выше. не могли бы вы подробнее рассказать, как это можно сделать без асихоничности?

WiredCoder 30.05.2018 02:32

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

WiredCoder 30.05.2018 02:40
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
124
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это соблюдает тайм-аут. Тайм-аут предназначен для обратного вызова, а не для выполнения функции. Итак, произошло то, что все ваши вызовы функций выполнялись асинхронно, и все они ждали пять секунд, и все они вернулись. Таким образом, все они прошли пять секунд между началом и завершением. Узлу не нужно ждать завершения первой функции до завершения второй.

В основном для нетривиального примера, то есть ожидания вызова db. вам не нужно ждать завершения одного вызова db перед отправкой второго вызова db. И если БД является многопоточным, вы можете получить результаты практически одновременно.

Это мое понимание, поправьте меня, если я ошибаюсь, это означает, что либо каждый вызов функции cookAndDeliver выполняется в отдельном потоке, либо каждый placeAnOrder выполняется в отдельном потоке

WiredCoder 30.05.2018 02:36

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

Eric Yang 30.05.2018 12:44
Ответ принят как подходящий

Вот последовательность событий:

  1. Позвоните сначала placeAnOrder()
  2. Он вызывает cookAndDeliver()
  3. Он вызывает setTimeout()
  4. setTimeout() планирует событие таймера на 5 секунд с этого момента и немедленно возвращается.
  5. Позвонить второму placeAnOrder()
  6. Он вызывает cookAndDeliver()
  7. Он вызывает setTimeout()
  8. setTimeout() планирует событие таймера на 5 секунд с этого момента и немедленно возвращается.
  9. Позвонить второму placeAnOrder()
  10. Он вызывает cookAndDeliver()
  11. Он вызывает setTimeout()
  12. setTimeout() планирует событие таймера на 5 секунд с этого момента и немедленно возвращается.
  13. Повторите это еще два раза, чтобы в общей сложности 5 таймеров сработали примерно через 5 секунд.
  14. Интерпретатор Javascript возвращает управление циклу обработки событий, поскольку какое-то время ему больше нечего делать.
  15. Затем примерно через 5 секунд внутренняя часть Javascript помещает первое событие таймера в очередь событий.
  16. Если интерпретатор Javascript ничего не делает в этот момент, он запускает это событие и вызывает обратный вызов, связанный с этим событием таймера.
  17. Этот обратный вызов выполняется.
  18. Когда этот обратный вызов выполняется, в очереди событий появляется другое событие таймера, и интерпретатор JS вызывает его обратный вызов для его обработки.
  19. После выполнения этого обратного вызова следующие 3 события таймера извлекаются по одному из очереди событий и выполняются их обратные вызовы.

Здесь нет веток Javascript. Javascript в node.js однопоточный. Все проходит через центральную очередь событий. В Javascript могут быть внутренние элементы, которые используют потоки для выполнения асинхронных операций (например, ввод-вывод асинхронного файла использует потоки, внутренние по отношению к его реализации, но не для запуска Javascript). Когда эти потоки завершены, они помещают событие в очередь событий, и когда единственный поток Javascript node.js завершает выполнение того, что он делал, он затем захватывает следующее событие из очереди событий и выполняет связанный с ним обратный вызов.

My guess is that since it operates in an asynchronous mode then it means that a separate thread is going to handle each call, is my assumption correct?

Нет, это не так. setTimeout() планирует событие таймера на некоторое время в будущем. Нет потока Javascript, связанного с событием таймера. Может быть или не быть одного системного потока, который управляет всеми событиями таймера (это зависит от реализации и на самом деле не имеет значения - также может быть, что всякий раз, когда Javascript возвращается в цикл событий, он просто проверяет, не пришло ли время запустить следующее событие таймера). Когда наступает время срабатывания таймера, событие вставляется в очередь событий Javascript. Затем интерпретатор JS выбирает это событие из цикла событий в следующий раз, когда он завершит обработку и ищет следующее событие для обработки.

An example was given on how Node provides better performance is shown below

Я думаю, что они пытались показать, что из-за асинхронной управляемой событиями конструкции node.js НЕ существует нескольких потоков для асинхронных событий, таких как таймеры. Это позволяет ему лучше масштабироваться при одновременном выполнении множества асинхронных операций, поскольку его модель более эффективна, чем модель, в которой для каждого таймера есть системный поток.

Should you run the sample, you will notice that first all order placed at once, which is normal, and then all of the orders are also delivered once, which is not normal since there is already a timeout constraint of 5 seconds applied per call.

По сути, код запускает 5 вызовов setTimeout() подряд, и все они устанавливают таймер на срабатывание через 5 секунд. setTimeout() не блокирует. Это означает, что он планирует таймер на 5 секунд с этого момента, а затем НЕМЕДЛЕННО переходит к следующей строке кода, которая также планирует таймер на 5 секунд с этого момента. Таким образом, вы получите 5 таймеров, все запланированные примерно на 5 секунд с этого момента (возможно, варьируется всего несколько миллисекунд времени выполнения от одного вызова setTimeout() до следующего. Конечным результатом является то, что все 5 таймеров сработают примерно через 5 секунд, и они будут срабатывать в том порядке, в котором они были запланированы.

The explanation given by the video was that the call back is none-obstructive and the code will execute unintrrupted, which I concur with, what I don't get is why the node did not honor the timeout value?

Поскольку setTimeout() не блокирует (как и все асинхронные операции в node.js). Он планирует таймер на некоторое время в будущем, а затем немедленно возвращается (это неблокирующая часть). Он не ждет 5 секунд, чтобы вернуться. Он немедленно возвращается и выполняет любой следующий код. Затем через 5 секунд (когда интерпретатору JS больше нечего делать) будет вызван обратный вызов таймера.

Другие вопросы по теме