NodeJs program flow - node.js

Currently still understanding the logic flow of a typical web application. In PHP, since its not async, typically we will have to wait for database insert/update to be completed before returning response to user.
But since in NodeJs we can have Async database query with callback and return response to user even before the callback is being called by database.
In these kind of situation, assuming validation of the data was already done, do typical nodeJs application wait for the callback before response or always assume the query is successful and return response to user?

I'm not entirely sure what you're asking but you should take a look at these explanations of async database queries:
Async explanation
Callback explanation
If I interpreted your question correctly you are asking when a node application would return a response, right? Typically you return a response to the user (like updating the client view) within the callback. By providing a callback you can make sure that the response is received and successful before moving on in that thread. Here is a bit of code to illustrate:
functionThatTakesForever(argument, function(error, response){ //this is the callback
if(error)
console.log(error);
else{
\\do something with response to return the response to the user
}
});

Related

NodeJs Execute function mutiple times without delay

i will share the code directly
app.get('/ListBooks', function (req, res) {
console.log("Function called");
//internally calls another URL and sends its response to browser
request({
url: 'someURLinRESTServer',
method: 'POST',
json: MyJsonData
}, function (error, response, body) {
if (error) {
console.log("/Call Failed ->" + error);
res.status(200).send('Failed');
} else {
console.log("/Call got Response");
console.log(response.statusCode, body);
res.send(body); res.end();
}
})
now when the browser generates a request on http://localhost/ListBooks
my node console shows the first message "Function called" and waits for internal REST URL Response
the real problem occurs only when the REST SERVER is down
then if i try to call http://localhost/ListBooks from another browser tab the Node server console doesnt show any changes and only after the repsonse of previous function REST CALL call it displays console message of second function call on app.get('/ListBooks'
i thought node js makes async functions bt here i dnt want functions to wait likes this for multiple instance calls
or is it just a delay in printing message and each function call executes separately .Plz clarify ...
If this is only occurring when the REST server is down (as your comment indicates), then that's just a function of how long your calls to request() take to fail. And, each separate call to request() goes through its own cycle of trying to connect and then eventually timing out. If both are timing out, then you will issue request1, then request2, then some timeout amount of time will pass and request1 will fail and then request2 will fail shortly after it. This has nothing to do with how express handles multiple requests and everything to do with how the calls to your REST server behave.
You can set the timeout option for request() if you want to shorten how long it will wait for a response, but you do need to make sure you don't shorten it so much that a busy REST server that just takes a little while to actually respond gets timed out.
or is it just a delay in printing message and each function call
executes separately
Each call is acting completely separately. There is no serialization of these responses by node.js or by Express. The appearance of serialization is just because they both take the same amount of time to fail with a timeout so they will fail one after the other.

NodeJS/SailsJS app database block

Understand that NodeJS is a single thread process, but if I have to run a long process database process, do I need to start a web worker to do that?
For example, in a sails JS app, I can call database to create record, but if the database call take times to finish, it will block other user from access the database.
Below are a sample code i tried
var test = function(cb) {
for(i=0;i<10000;i++) {
Company.create({companyName:'Walter Jr'+i}).exec(cb);
}
}
test(function(err,result){
});
console.log("return to client");
return res.view('cargo/view',{
model:result
});
On first request, I see the return almost instant. But if I request it again, I will need to wait for all the records being entered before It will return me the view again.
What is the common practice for this kinda of blocking issue?
Node.js has non-blocking, asynchronous IO.
read the article below it will help you to restructure your code
http://hueniverse.com/2011/06/29/the-style-of-non-blocking/
Also start using Promises to help you avoid writing blocking IO.

How to make asynchronous call to mongoDB inside Connect middleware?

Lets say I have the following Express/Connect middleware:
return function(req, res, next) {
mongoose.connect(url, options);
var Config = mongoose.model('Config', mongoose.Schema({
field1: Boolean,
field2: []
}));
Config.findOne({}, function (err, doc) {
if(!err) {
if(someCondition)
// some logic: send response and interrupt middleware chain
res.end('Some response');
else
next();
}
}
};
The issue is that database call is asynchronous. So middleware function exits before any logic executed.
The task is simple: read the configuration from mongoDB and if some field value = 'something" send response, otherwise - continue middleware chain.
So, I have 2 questions at the moment:
Is there any way to make asynchronous calls inside middleware?
If not, is there any workaround? (AFAIK, there is no way to execute db call synchronously)
So middleware function exits before any logic executed.
Yes, but this is totally normal and 100% OK for node.js asynchronous code. That's how asynchronous code works. When the DB call completes, control flow resumes and you can either send a response or call next() at that time. This is fine.
Is there any way to make asynchronous calls inside middleware?
Yes, and the way you are doing it is fine (minus some minor caveats listed below).
If not, is there any workaround?
No workaround necessary. This is how node.js works by design. All network I/O in node.js is asynchronous.
A few minor notes
Make sure you either send a response OR call next() in every possible branch of your database callback function logic: error, someCondition is true, and someCondition is false. If any of your logic can end up in a branch that doesn't respond to the request and doesn't call next() the request will just hang until it fails due to a timeout. Your snippet above is missing error handling, which you need to do.
Move your mongoose connect call to application startup time. Don't connect on each request.
Move your mongoose model definition out to a separate module Config.js

How return result from request, and after perform async task but without callback in NodeJS

iOS application perform request for sending messages to users. I want to return result to application, and after that send push notification to users, and I don't want to wait until notifications were pushed successfully or not.
app.post("/message", function(req, res, next) {
User.sendMessages(query, options, function(err, results) {
res.json(results);
sendPushNotifications();
});
});
How can I do this?
That's how it works.
Keep in mind everything that happens in node is in a single thread, unlike other back-end languages you might be used to.
Requests, jobs, everything happens in that single thread. Unless, of course, you use cluster or something like that.

node.js wait for response

I have a very limited knowledge about node and nob-blocking IO so forgive me if my question is too naive.
In order to return needed information in response body, I need to
Make a call to 3rd party API
Wait for response
Add some modifications and return JSON response with the information I got from API.
My question is.. how can I wait for response? Or is it possible to send the information to the client only when I received response from API (as far as I know, connection should be bidirectional in this case which means I won't be able to do so using HTTP).
And yet another question. If one request waits for response from API, does this mean than other users will be forced to wait too (since node is single-threaded) until I increase numbers of threads/processes from 1 to N?
You pass a callback to the function which calls the service. If the service is a database, for example:
db.connect(host, callback);
And somewhere else in the code:
var callback = function(err, dbObject) {
// The connection was made, it's safe to handle the code here
console.log(dbObject.status);
res.json(jsonObject, 200)
};
Or you can use anonymous functions, so:
db.connect(host, function(err, dbObject) {
// The connection was made, it's safe to handle the code here
console.log(dbObject.status);
res.json(jsonObject, 200)
});
Between the call and the callback, node handles other clients / connections freely, "non-blocking".
This type of situation is exactly what node was designed to solve. Once you receive the request from your client, you can make a http request, which should take a callback parameter. This will call your callback function when the request is done, but node can do other work (including serving other clients) while you are waiting for the response. Once the request is done, you can have your code return the response to the client that is still waiting.
The amount of memory and CPU used by the node process will increase as additional clients connect to it, but only one process is needed to handle many simultaneous clients.
Node focuses on doing slow I/O asynchronously, so that the application code can start a task, and then have code start executing again after the I/O has completed.
An typical example might make it clear. We make a call to the FB API. When we get a response, we modify it and then send JSON to the user.
var express = require('express');
var fb = require('facebook-js');
app.get('/user', function(req, res){
fb.apiCall('GET', '/me/', {access_token: access_token}, function(error, response, body){ // access FB API
// when FB responds this part of the code will execute
if (error){
throw new Error('Error getting user information');
}
body.platform = 'Facebook' // modify the Facebook response, available as JSON in body
res.json(body); // send the response to client
});
});

Resources