Как правильно сделать асинхронный запрос времени в узле - PullRequest
0 голосов
/ 12 февраля 2019

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

Я уже использовал обещания для асинхронных задач, но насколько я понимаю обещания, действительно асинхронная часть - это обработчики then и catch.Когда создается обещание, функция-исполнитель будет выполняться основным потоком до тех пор, пока она не выполнит какую-либо асинхронную задачу (setTimeout и т. Д.).

Пример кода отправки электронной почты

   app.route('/api/contact/sendEmail')
       .post((req, res) =>{
           sendEmail(req).then( () =>{
               res.status(200);
               res.json({
                   sent: true
               });
           }).catch(emailError=> {
               //Custom error send bad request.
               if(emailError.code === 900) {
                   res.status(400);
                   res.json({
                       errorCode: emailError.code,
                       message: emailError.message
                   });
               }else {
                   res.status(500);
                   res.json({
                       errorCode: emailError.code
                   });
               }
           });
       });

Потокне блокируется для отправки ответа, но пока sendEmail не достигнет фактической асинхронной части, основной поток будет заблокирован

1 Ответ

0 голосов
/ 12 февраля 2019

Сложно ответить на ваш вопрос, так как вы не предоставляете подробную информацию о библиотеке / функциях, которые вы используете, например, откуда берется функция sendMail, что такое app и в какой момент выдумаю, что-то блокирует.

Однако, в общем случае, ваш код в Node.JS всегда выполняется в mainthread.Это означает, что каждая строка вашего файла .js находится в основном потоке, независимо от того, является ли что-то «асинхронным» или нет.

Теперь, чтобы фактически позволить чему-то быть "асинхронным" (то есть: выполняется , в то время как выполняется другой код), должен быть способ поместить материал в другой поток для выполнения.И это то, что на самом деле происходит в Node.JS под капотом.Node.JS использует libuv / libev для реализации цикла событий для обработки задач.Он также имеет ряд фоновых / рабочих потоков (по умолчанию 4), которые выполняют задачи блокировки, например, сетевой или файловый ввод-вывод.

Однако, это абстракция от разработчика Node.JS, потому что она скрыта в реализации соответствующего модуля .Например, встроенная файловая система или сетевые модули будут выполнять свои задачи в фоновом потоке (если вы не используете один из вариантов функции -sync).Если вы используете сторонний модуль, это зависит от того, написан ли он на C / C ++ и использует libuv для доступа к рабочим потокам и выполнения фоновой обработки.Если это не так, то ваш сторонний модуль выполнит код в основной потоке так же, как и ваш код, если это так, то выполнение действительно выполняется «асинхронно» / в фоновом потоке.

Пожалуйста, посмотрите также это очень информативнонить: Как работает однопоточная неблокирующая модель ввода-вывода в Node.js

Как это вам поможет?
По сути, я хотел сказать, что этовсе зависит от функций / модулей, которые вы используете, и от того, реализованы ли они как фоновые операции (с использованием libuv) или нет.Кроме того, вы не можете сделать что-либо асинхронным / синхронизировать самостоятельно, вы обязаны использовать все, что реализует функция / модуль.

Для полноты картины я хотел бы отметить, что Node.JS 11 представил worker_threadsмодуль, который позволяет использовать потоки в коде javascript, что позволяет вам помещать что-то в фоновый поток, а не блокировать основную тему.Обратите внимание, что стабильность модуля все еще "экспериментальная".

Sidenote
Вы действительно уверены, что ваш код блокирует основную нить ?Поскольку, как упоминалось ранее, сетевой ввод-вывод в любом случае происходит в фоновых потоках, поэтому маловероятно, что sendMail блокирует основную резьбу (при условии, что задача sendMail заключается в выполнении сетевого ввода-вывода).Как вы узнали, что он блокирует?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...