Issue
I am not sure if this is expected behaviour or not.
in Server.ts I handle a POST request that requires heavy calculation:
app.post("/get-topics", async (req: Request, res: Response)=>{
const posts = await pool.query(`<my sql search string here>`, [req.body.user]);
const postText: string[] = posts.rows.map(p => p.content);
const results = lda(postText, 5, 3); //takes 1 minute to finish executing
res.json({'topics':results})
})
The function lda
takes a minute to finish executing. When this is happening, basically the server is blocked. No HTTP requests can be made. I find this strange as it is in an async function so I would assume all the other app.get
and app.post
events would happen?
My question is, how can I get the server to handle other http requests while lda is executing? Or is this not possible in Node.js?
Edit: for context I am using Express, and the lda
function is a node module (https://github.com/primaryobjects/lda/blob/master/lib/lda.js) which runs a statistical analysis on an array of strings.
Solution
Nodejs is an event-driven system that runs your javascript in a single thread. It uses threads internally in its implementation, but other than a child process or a WorkerThread, it runs your javascript in just a single thread. It works for responsive servers because most of what servers are doing is I/O to the file system, network or databases and nodejs has non-blocking, asynchronous APIs for those types of operations which allow nodejs to do other things while those APIs are doing their work. This works for most types of http servers and many other types of servers.
If this line of code:
const results = lda(postText, 5, 3);
takes a minute to process synchronously, then it will block nodejs from running any of your Javascript for that minute. That's how nodejs works. It's an event-driven system that runs your Javascript in a single thread. So, it can't service the next event until the prior one returns control back to the system.
The fact that it's running inside an async
function doesn't change any of that. async
just enables the use of await
for awaiting a promise and converts exceptions into a rejected promise. It doesn't magically make blocking, synchronous code into asynchronous code.
My question is, how can I get the server to handle other http requests while lda is executing? Or is this not possible in Node.js?
First off, don't do any long running synchronous code in the main Javascript thread. It doesn't appear that the lda code is designed to run in a nodejs server in the way you are using it because it appears to be long-running, synchronous, blocking code.
Second, if you absolutely have to run long running, blocking and synchronous code, then you have to move it out of the main Javascript thread, either to a child process or to a WorkerThread. Nodejs programs that have to do heavy encoding or encrypting or image analysis or such will typically create some sort of thread pool so that work can be passed off to another thread and then the main thread is free to service other events from the event queue (e.g. process other connections).
Answered By - jfriend00
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.