I'm working on a NodeJS/Express program and I'm trying to get a POST request to return data. When I return a direct string, I get the correct response.
app.post("/DoStuff", function(req, res, Data) {
DoStuf.DoStuffFunction(req.body.UserID, function(label) {
Data = label
})
res.send({message: "Stuff"});
})
When I change it to return a variable (which is still a string) it only returns "{}".
app.post("/DoStuff", function(req, res, Data) {
DoStuf.DoStuffFunction(req.body.UserID, function(label) {
Data = label
})
res.send({message: Data});
})
Even when I make Data = "foo" the response is "{}"
You need to send from inside of callback function. In your code res.send is independent of DoStuffFunction's callback
app.post("/DoStuff", function(req, res, Data) {
DoStuf.DoStuffFunction(req.body.UserID, function(label) {
Data = label;
res.send({message: Data});
})
})
Looks like your DoStuffFunction is async. So just move res.send(..) in callback.Something like
app.post("/DoStuff", function(req, res, Data) {
DoStuf.DoStuffFunction(req.body.UserID, function(label) {
res.send({message: label});
})
})
When I change it to return a variable (which is still a string) it only returns "{}".
This is because DoStuf.DoStuffFunction(){} is asynchronous.
The reason why it works when you use stuff as value is because the operation is synchronous. And you have value with you before sending the response.
If you want to send response only after the DoStuffFunction() completes, place the response.send() within the callback.
'use strict';
app.post("/DoStuff", function(req, res, Data) {
DoStuf.DoStuffFunction(req.body.UserID, function(label) {
res.send({message: label}); //you can send label's value directly
});
});
Related
I've written a small database function that gets some data from the DB and puts it into the format that I want, but I'm having difficulties returning the data to display it with Express. The database function is as follows:
function getAllEvents(req, res, next) {
db.any('select * from sensors, events where sensors.sensorid = events.sensorid')
.then(function (data) {
var final = [];
data.forEach(function(datas){
if (!final[datas.sensorid]){
final[datas.sensorid] = {};
}
if (!final[datas.sensorid].name){
final[datas.sensorid].name = datas.name;
final[datas.sensorid].signatures = {};
}
if (!final[datas.sensorid].signatures[datas.signature]){
final[datas.sensorid].signatures[datas.signature] = {};
final[datas.sensorid].signatures[datas.signature].id = "sen" + datas.sensorid + "sig" + datas.signature;
final[datas.sensorid].signatures[datas.signature].signature = datas.signature;
final[datas.sensorid].signatures[datas.signature].message = datas.message;
final[datas.sensorid].signatures[datas.signature].events = {};
}
final[datas.sensorid].signatures[datas.signature].events[datas.eventid] = datas;
})
return final;
})
.catch(function (err) {
console.log("Something went wrong! ", err)
});
}
And the router function to call it is this:
router.get('/events', function(req, res, next) {
db.getAllEvents(function(err, data){
res.render('events', { data: data });
});
});
I think the router function is waiting indefinitely for the data though as I get no errors but the page never loads. What am I doing wrong?
What am I doing wrong?
This code:
router.get('/events', function(req, res, next) {
db.getAllEvents(function(err, data){
res.render('events', { data: data });
});
});
is ok besides the fact that you are not checking for errors. Notice that getAllEvents is expecting a function as an argument.
now Let's look at your getAllEvents function prototype
function getAllEvents(req, res, next) {
It is simply not correct and should have been something like
function getAllEvents(callback) {
Then you would be able to call the callback and "return" the result like this
return callback(null,data);
or if an error occurred during you database connection pass the error to the callback
return callback(err);
I have a request handler for a particular route that does something like the following:
function doThing(req, res) {
res.json({ "thing" : "thing", "otherThing": externalModule.someFunction("yay"); });
}
It seems like the result is being send before the "someFunction" call completes, so the "otherThing" JSON is always non-existent. How can I wait for that function to return data before sending a response?
Use callbacks. Example:
externalModule.someFunction = function(str, cb) {
// your logic here ...
// ... then execute the callback when you're finally done,
// with error argument first if applicable
cb(null, str + str);
};
// ...
function doThing(req, res, next) {
externalModule.someFunction("yay", function(err, result) {
if (err) return next(err);
res.json({ "thing" : "thing", "otherThing": result });
});
}
When I have a simple function processing the request I can use res.end() and return to end it at any point (some error happened/incorrect data, etc.)
get('/', function (req, res) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end(); // <-- response is ready, send it to client
return; // <-- request processing stops here, get() finishes
}
// do other stuff
res.send('ok'); // <-- this can never overlap with the previous res.send()
});
However, if there are functions embedded in other functions, return will only quit the last one
get('/', function (req, res) {
validate(req);
// do other stuff
res.send('ok'); // <-- this can cause errors? res was ended already
});
function validate(req, res) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end(); // <-- send response to client
return; // <-- this one exists only from validate()
}
}
I believe to send the response to client res.end() should be called, but how can I stop further code from processing - i.e. return from all functions?
It is impossible to return from a called function, just use a callback as below:
function validate(req, res, callback) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end();
} else {
callback();
}
}
get('/', function (req, res) {
validate(req, function () {
res.send('ok');
});
});
You could return true or false in validate function depending on if you had already sent response.
But, it's not node style. Using callbacks is preferred in node.
I know this is an old question but may be helpful for others. You could use res.headersSent like this
get('/', function (req, res) {
validate(req);
// will only be sent if validate hasn't already sent the error message
if(!res.headersSent) {
res.send('ok');
}
});
function validate(req, res) {
if (!req.param('id')) {
res.send('Must provide ID!');
res.end();
}
}
i'm having a problem in posting/inserting a data in my redis database via POST method. By the way i'm using expressjs as framework and here is my code:
app.post('/create/:id', function (req, res) {
return client.set(req.params.id, req.params.val, function (err, data) {
if (!err) {
return res.send(data);
} else {
return console.log(err);
}
});
});
Is there any correction here? My goal is to post data like this http://mydomain:45/create/2/test is it possible? or do I need only to POST it to /create with the id and the value of that id? Thanks guys. I hope you can help me. :)
You are setting the value of req.params.id as the key, and the possibly undefined value of req.params.val as the value. You should set the req.body.val instead of req.params.val, if you are POST-ing with a request body.
Try with the following changes:
app.post('/create/:id', function (req, res) {
return client.set(req.params.id, req.body.val, function (err, data) {
if (!err) {
return res.send(data);
} else {
return console.log(err);
}
});
});
And run POST /create/123 with the body val=myValue.
I am working on a NodeJs project for the first time. And now i am stuck with the function returning values through JS and getting values to use in express.
var dbitems = "before fn";
function refreshData(callback) {
db.open(function (err, db) {
if (!err) {
db.collection('emp').find().toArray(function (err, items) {
dbitems = items;
callback(JSON.stringify(items));
});
}
else {
console.log("Could not be connnected" + err);
dbitems = {"value":"not found"};
}
});
}
}
refreshData(function (id) { console.log(id); });
This function retrieves values perfectly from refreshData and writes into console. But what I need is to use the retrieved value to send into express html file from this function by "returnedData"
exports.index = function (req, res) {
var valrs = refreshData(function (id) {
console.log(JSON.parse(id)); ---this again writes data perfectly in the console
});
console.log(valrs); -------------------but again resulting in undefined
res.render('index', { title: 'Express test', returnedData: valrs });
};
Any help would be appreciated.
Thanks & Regards,
Luckyy.
You need to render this after the database request finishes.. so it needs to be called from within the callback.
exports.index = function (req, res) {
refreshData(function (id) {
res.render('index', { title: 'Express test', returnedData: JSON.parse(id) });
});
};
it's asynchronous so you can't just put values in order, needs to go through the callbacks.