how to run asynchronous function synchronously in node js - node.js

I am Using Express framework.
The problem I am facing is that I have created a var duration and when a request at '/' is received it simply find the total duration of given video and save to that variable but at the end I want to show that variable but instead of showing that variable value it shows nothing and in console in shows undefined...
can anyone please please help me to tun this code synchronously instead of asynchronous...
thanks alot
This is my code

to handle the asynchronous code you need to put
console.log(duration);
res.send(duration);
inside the callback of exec.
modified code:
var duration;
app.get('/', function(req, res){
exec('ffprobe -1 ***', function(){
if(stdout){
duration = stdout;
console.log(duration);
res.send(duration);
}
});
});

Related

Node.js filesystem work causes 500 server error

I'm testing some code by using node express framework and ajax.
I'm facing a problem that I get a 500 server error in the front-end side.
Server-size nodejs code is like below(Very simple).
This is the code for express router.
Once I add some code about filesystem work like below, I get an 500 error.
But, if I remove the line about readdirSync function call, it works well.
I don't understand what in the world may cause this kind of problem.
I know the synchronous function is not so good for here, but it's just some simple test.
router.post('/pictureListFromFile', function(req, res, next) {
var dirPath = "../public/img/laos1";
var fileList = [];
// fileList = fs.readdirSync(dirPath); // --> This code cause the problem.
console.log(fileList);
// response here for ajax
});
With readdirSync, as in most synchronous call in node, if there is an error, it will throw an error, crashing your server.
Never use synchronous call with node, the error management is based on try/catch and it do not scale well (it's actually freezing the entire node process).
Use the callback style :
fs.readdir(dirPath, function (err, files){
// rest of the code including res.send
});
var fs = require('fs'); //if there is none
var fileList = [];
fileList.push(); //use push if you want to add to the array
But what causes the error in:
fs.readdirSync(dirPath);
is that dirPath is invalid. You have to use __dirname + path you need instead, or specify the correct path (C:/Program Files/...).

NodeJS readdir() function always being run twice

I've been trying to pick up NodeJS and learning more for backend development purposes. I can't seem to wrap my mind around Async tasks though and I have an example here that I've spent hours over trying to search for the solution.
app.get('/initialize_all_pictures', function(req, res){
var path = './images/';
fs.readdir(path, function(err, items){
if (err){
console.log("there was an error");
return;
}
console.log(items.length);
for(var i = 0; i<items.length; i++){
var photo = new Photo(path + items[i], 0, 0,Math.floor(Math.random()*1000))
photoArray.push(photo);
}
});
res.json({"Success" : "Done"});
});
Currently, I have this endpoint that is supposed to look through a directory called images and create "Photo" objects and push it into a global array called PhotoArray. It works, except the function for readdir is always being called twice.
console.log would always give output of
2
2
(I have two items in the directory).
Why is this?
Just figured out the problem.
I had a chrome extension that would help me format JSON values from HTTP requests. Unfortunately, the extension actually made an additional call to the endpoint therefore whenever I would point my browser to the endpoint, the function would end up getting called twice!

Returning variable value in sailsJS

I am trying to write a controller in sailsjs
module.exports = {
someFunction: function(req, res){
var userID = req.param('id')
User.findUserName(userID, function(err, receiverName){
if(err){
res.serverError(err);
}else{
ReceiverName = receiverName;
}
});
console.log("#####################################");
console.log(ReceiverName);
console.log("#####################################");
.
.
.
.
But when I deploy the controller, restart the sails app and call this function through the URL, I am getting the following error on the console:
error: Sending 500 ("Server Error") response:
ReferenceError: ReceiverName is not defined
I tried to declare the variable ReceiverName to be global, but still cant sort it out. I need guidance on making it global so that I assign value to it inside the else part and use it anywhere inside the controller.
Note 1:
However, when I am printing the value of the variable on console right inside the else block using the code:
User.findUserName(userID, function(err, receiverName){
if(err){
res.serverError(err);
}else{
console.log("#####################################");
console.log(receiverName);
console.log("#####################################");
}
});
the value is printed perfectly.
Note 2:
I am already making asynchronous call to retrieve the receiverName, so it is not a doubt about returning the response from asynchronous calls. I am looking for method to store the response in a variable that can be used further.
Your Note 2 is a little bit confusing so I'm not sure if you understand that the reason it does not work in your first example is because the User.findUserName() has not finished running before you execute your console.log().
Remember, the database calls are async. So any values you want to use from that database call have to run after it finishes. The only way to ensure that is to make sure your code runs inside the callback.
That is why the second example works. The code that needed the receiverName variable ran inside the callback. Try this, it is pretty much the same thing as your second example ...
User.findUserName(userID, function(err, receiverName){
if(err){
res.serverError(err);
}else{
doStuffWith(receiverName)
}
});
var dostuffWith = function(ReceiverName){
// all the code that you want to use ReceiverName should be in here.
console.log("#####################################");
console.log(ReceiverName);
console.log("#####################################");
}
You should do some reading on programming patterns with Node.js, async and callbacks. Like this
http://book.mixu.net/node/ch7.html

Store settimeout id from nodejs in mongodb

I am running a web application using express and nodejs. I have a request to a particular endpoint in which I use settimeout to call a particular function repeatedly after varying time intervals.
For example
router.get ("/playback", function(req, res) {
// Define callback here ...
....
var timeoutone = settimeout(callback, 1000);
var timeouttwo = settimeout(callback, 2000);
var timeoutthree = settimeout(callback, 3000);
});
The settimeout function returns an object with a circular reference. When trying to save this into mongodb i get a stack_overflow error. My aim is to be able to save these objects returned by settimeout into the database.
I have another endpoint called cancel playback which when called, will retrieve these timeout objects and call cleartimeout passing them in as an argument. How do I go about saving these timeout objects to the database ? Or is there a better way of clearing the timeouts than having to save them to the database. Thanks in advance for any help provided.
You cannot save live JavaScript objects in the database! Maybe you can store a string or JSON or similar reference to them, but not the actual object, and you cannot reload them later.
Edit: Also, I've just noticed you're using setTimeout for repeating stuff. If you need to repeat it on regular intervals, why not use setInterval instead?
Here is a simple solution, that would keep indexes in memory:
var timeouts = {};
var index = 0;
// route to set the timeout somewhere
router.get('/playback', function(req, res) {
timeouts['timeout-' + index] = setTimeout(ccb, 1000);
storeIndexValueSomewhere(index)
.then(function(){
res.json({timeoutIndex: index});
index++;
});
}
// another route that gets timeout indexes from that mongodb somehow
req.get('/playback/indexes', handler);
// finally a delete route
router.delete('/playback/:index', function(req, res) {
var index = 'timeout-' + req.params.index;
if (!timeouts[index]) {
return res.status(404).json({message: 'No job with that index'});
} else {
timeouts[index].cancelTimeout();
timeouts[index] = undefined;
return res.json({message: 'Removed job'});
}
});
But this probably would not scale to many millions of jobs.
A more complex solution, and perhaps more appropriate to your needs (depends on your playback job type) could involve job brokers or message queues, clusters and workers that subscribe to something they can listen to for their own job cancel signals etc.
I hope this helps you a little to clear up your requirements.

nodejs and expressjs

app.get('/', function(req, res) {
res.set('Content-Type', 'text/html');
res.send('Yo');
setTimeout(function(){
res.send("Yo");
},1000);
});
It looks like "send" ends the request. How can I get this to write Yo on the screen and then 1 second later (sort of like long polling I guess) write the other Yo to get YoYo? Is there some other method other than send?
Use res.write to generate output in pieces and then complete the response with res.end.
I don't think what you are trying to do is possible.
Once you send a response, the client-server connection will be closed.
Look into sockets (particularly socket.io) in order to keep a connection open and send multiple messages on it.
Try with JQuery+JSON. send the response and then update what ever you need with JQuery and JSON.
This is a good tutorial of expressjs, including DB stuff (mongodb).
If you want to send the result as a single block try
app.get('/', function(req, res) {
res.set('Content-Type', 'text/html');
res.write('Yo');
setTimeout(function(){
res.end("Yo");
},1000);
});
or something like
app.get('/', function(req, res) {
res.set('Content-Type', 'text/html');
var str = 'yo';
setTimeout(function(){
res.end(str + 'yo');
},1000);
});
the thing with node.js is that it relies on an asynchronous "style". so if you introduce something like a "wait" function, you'll lose all the benefits of the asynchronous way of execution.
I believe you can achieve something similar to what you want by:
(asynchronous way) including a function that prints the second "Yo" as a callback to
the first function (or)
(classic wait(synchronous) ) introduce a 'big' loop before presenting the second 'Yo'.
for example:
for(i=0; i < 100000000; i++) {
//do something
}

Resources