MOCKSTACKS
EN
Questions And Answers

More Tutorials









NodeJS Performance challenges

Processing long running queries with Node


Since Node is single-threaded, there is a need of workaround if it comes to a long-running calculations.

Note: this is "ready to run" example. Just, don't forget to get jQuery and install the required modules.

Main logic of this example:


1. Client sends request to the server.
2. Server starts the routine in separate node instance and sends immediate response back with related task ID.
3. Client continiously sends checks to a server for status updates of the given task ID.


Project structure:


 project
 │ package.json
 │ index.html
 │
 ├───js
 │ main.js
 │ jquery-1.12.0.min.js
 │
 └───srv
 │ app.js
 ├─── models
 │ task.js
 └─── tasks
 data-processor.js

app.js:


var express = require('express');
var app = express();
var http = require('http').Server(app);
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var childProcess= require('child_process');
var Task = require('./models/task');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/../'));
app.get('/', function(request, response){
 response.render('index.html');
});
//route for the request itself
app.post('/long-running-request', function(request, response){
 //create new task item for status tracking
 var t = new Task({ status: 'Starting ...' });
t.save(function(err, task){
 //create new instance of node for running separate task in another thread
 taskProcessor = childProcess.fork('./srv/tasks/data-processor.js');
 //process the messages comming from the task processor
 taskProcessor.on('message', function(msg){
 task.status = msg.status;
 task.save();
 }.bind(this));
 //remove previously openned node instance when we finished
 taskProcessor.on('close', function(msg){
 this.kill();
 });
 //send some params to our separate task
 var params = {
 message: 'Hello from main thread'
 };
 taskProcessor.send(params);
 response.status(200).json(task);
 });
});
//route to check is the request is finished the calculations
app.post('/is-ready', function(request, response){
 Task
 .findById(request.body.id)
 .exec(function(err, task){
 response.status(200).json(task);
 });
});
mongoose.connect('mongodb://localhost/test');
http.listen('1234');

task.js:


var mongoose = require('mongoose');
var taskSchema = mongoose.Schema({
 status: {
 type: String
 }
});
mongoose.model('Task', taskSchema);
module.exports = mongoose.model('Task');

data-processor.js:


process.on('message', function(msg){
 init = function(){
 processData(msg.message);
 }.bind(this)();

 function processData(message){
 //send status update to the main app
 process.send({ status: 'We have started processing your data.' });
//long calculations ..
 setTimeout(function(){
 process.send({ status: 'Done!' });

 //notify node, that we are done with this task
 process.disconnect();
 }, 5000);
 }
});
process.on('uncaughtException',function(err){
 console.log("Error happened: " + err.message + "\n" + err.stack + ".\n");
 console.log("Gracefully finish the routine.");
});

index.html:


<!DOCTYPE html>
<html>
 <head>
 <script src="./js/jquery-1.12.0.min.js"></script>
 <script src="./js/main.js"></script>
 </head>
 <body>
 <p>Example of processing long-running node requests.</p>
 <button id="go" type="button">Run</button>

 <br />

 <p>Log:</p>
 <textarea id="log" rows="20" cols="50"></textarea>
 </body>
</html>

main.js:


$(document).on('ready', function(){

 $('#go').on('click', function(e){
 //clear log
 $("#log").val('');

 $.post("/long-running-request", {some_params: 'params' })
 .done(function(task){
 $("#log").val( $("#log").val() + '\n' + task.status);

 //function for tracking the status of the task
 function updateStatus(){
 $.post("/is-ready", {id: task._id })
 .done(function(response){
 $("#log").val( $("#log").val() + '\n' + response.status);

 if(response.status != 'Done!'){
 checkTaskTimeout = setTimeout(updateStatus, 500);
 }
 });
 }

 //start checking the task
 var checkTaskTimeout = setTimeout(updateStatus, 100);
 });
});
});

package.json:


{
 "name": "nodeProcessor",
 "dependencies": {
 "body-parser": "^1.15.2",
 "express": "^4.14.0",
 "html": "0.0.10",
 "mongoose": "^4.5.5"
 }
}

Disclaimer: this example is intended to give you basic idea. To use it in production environment, it needs improvements.

Conclusion

In this page (written and validated by ) you learned about NodeJS Performance challenges . What's Next? If you are interested in completing NodeJS tutorial, your next topic will be learning about: NodeJS Send Web Notification.



Incorrect info or code snippet? We take very seriously the accuracy of the information provided on our website. We also make sure to test all snippets and examples provided for each section. If you find any incorrect information, please send us an email about the issue: mockstacks@gmail.com.


Share On:


Mockstacks was launched to help beginners learn programming languages; the site is optimized with no Ads as, Ads might slow down the performance. We also don't track any personal information; we also don't collect any kind of data unless the user provided us a corrected information. Almost all examples have been tested. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. By using Mockstacks.com, you agree to have read and accepted our terms of use, cookies and privacy policy.