Saurav Seth
Saurav Seth

Reputation: 311

How to truly make a time consuming request async in node

I am trying to scale my nodejs app so that it can efficiently handle multiple requests at the same time. One way of achieving this is through code optimization and i wanted to know how I can make time consuming requests async, are promises the only way? or is there another mechanism to achieve the same?

I have already used promises for async tasks but as far as i understand promises, the truly async part is the then and catch handlers. When one creates a promise the executor function will be executed by the main thread until it does some async task (setTimeout, etc).

Sample code of send email

   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
                   });
               }
           });
       });

The thread is not blocked to send the response but until the sendEmail does not reach the actual async part, the main thread will be blocked

Upvotes: 0

Views: 780

Answers (1)

user826955
user826955

Reputation: 3206

Its a bit hard to answer your question since you don't give details about the library/functions you're using, e.g. where the sendMail function is coming from, what app is, and at what point you think something is blocking.

However, in general, your code in Node.JS is always executed in the mainthread. That means, every line your .js file is in the main thread, no matter if anything is "async" or not.

Now, to actually allow something to be "async" (that is: beeing executed while other code is executed), there must be a way to shove stuff into another thread for execution. And this is, what is actually happening in Node.JS under the hood. Node.JS uses libuv / libev to implement an event loop to process tasks. It also features a number of background/worker threads (by default it is 4), which carry out blocking tasks, for example network or file I/O.

However, this is abstracted away from the Node.JS developer, because it is buried in the implementation of the corresponding module. For example, the builtin filesystem or network modules will carry out their tasks in a background thread (unless you use one of the -sync function variants). If you're using a third party module, it depends if it is written in C/C++ and uses libuv to access worker threads and do background processing. If it is not, then your thirdparty module will execute code on the mainthread same as your code, if it is, than execution is really done "async"/in a background thread.

Please also see this very informative thread: How the single threaded non blocking IO model works in Node.js

How does this help you?
Basically I wanted to tell you that it all depends on the functions/modules you are using, and whether or not they are implemented as background operation (using libuv) or not. On top of that, you cannot make anything async/sync yourself, youre bound to use whatever the function/module implements.

For completeness sake I'd like to mention that Node.JS 11 introduced the worker_threads module, which allows to use threads within javascript code, thus allowing you to put something in a background thread and not block the mainthread. Please note that the stability of the module is still "experimental".

Sidenote
Are you really sure that your code is blocking the mainthread? Because as mentioned before, network IO happens in background threads anyway, so it is unlikely that sendMail is blocking the mainthread (assuming that sendMails job is to do network IO). How did you find out it is blocking?

Upvotes: 2

Related Questions