how to write response in switch case using nodejs - node.js

In console it shows response but in postman shows sending request like that only. How can I return a valid response in postman. How can I write code for this one i tried all.
This is my code so far:
var sendStreamingTemplate = function (req, res) {
authToken = req.headers.authorization;
userAuthObj = JSON.parse(UserAuthServices.userAuthTokenValidator(authToken));
var todayDate = new Date();
var expireDate = new Date(userAuthObj.expire_date);
tokenOK = TokenValidator.validateToken(userAuthObj.user_id, authToken).then(function (userSessions) {
if (userSessions.length === 1) {
if (expireDate >= todayDate) {
StreamingTemplateId = req.params.id;
Template.findById(StreamingTemplateId).then(function (streamingTemplate) {
if (streamingTemplate === null) {
res.status(404).json({
message: 'Streaming not found...'
})
} else {
console.log(streamingTemplate);
switch(streamingTemplate.template_name.toString().toLowerCase()){
case "notification":
//if write return response means it will return something went wrong
break;
case "invoice":
break;
case "voucher":
break;
default:
break;
}
}
}).catch(function (err) {
res.status(500).json({
message: 'something went wrong...'
});
});
} else {
res.status(401).json({
message: 'Not Authorized...'
});
}
} else {
res.status(401).json({
message: 'Token Expired...'
});
}
}).catch(function (err) {
res.status(401).json({
message: 'Token Expired...'
});
});
};
This is the the output in the console:
Instance {
dataValues: {
id: 1, template_name: 'StreamNotification', description: 'Streaming', template_content: 'Mail notification', is_active: true
},
_previousDataValues: {
id: 1, template_name: 'StreamNotification', description: 'Streaming', template_content: 'Mail notification', is_active: true
},
_changed: {
},
}

It looks like when you hit the switch statement the code isn't setting the response. Try adding this immediately after your console.log line:
res.json(streamingTemplate)
or even
res.send(streamingTemplate)
depending on the type of streamingTemplate. You might need to vary the response depending on the switch statement, in which case you could set some return value in each case then move the response to the end of the switch. Depends what you are trying to do.

Related

If statement in nodejs not executing in order

Below is controller.js script. I am facing hard time to go inside if loop "if(changeUserToSellerFlag == 1)" because this if statement is executed much earlier than this if statement "if (results.Name == "Customer")". I am not sure why the order of execution is not done line by line.
const { updateUserSellerStatus } = require("./seller.model.js");
const { genSaltSync, hashSync } = require("bcrypt");
const userid = require("../auth/token_validation.js");
const {
updateUserRoleAfterSellerApproval,
getRoleName,
} = require("../users/user.service.js");
module.exports = {
sellerVerify: (req, res) => {
var sellerStatusName;
var changeUserToSellerFlag = 0; // this flag determines if user to seller update is needed or not
approvedByName = req.fullName; //get full name from token_validation.js
approvedByEmail = req.email; //get email from token_validation.js
console.log("Request body is below");
console.log(req.body); // contains body sent by postman
updateUserSellerStatus(
req.body,
approvedByName,
approvedByEmail,
(err, results) => {
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
if (req.body.sellerStatus == 3) {
sellerStatusName = "Rejected";
} else if (req.body.sellerStatus == 2) {
sellerStatusName = "Completed";
} else if (req.body.sellerStatus == 1) {
sellerStatusName = "Pending";
}
//verify if user is a seller or not
if (req.userId) {
getRoleName(req.userId, (err, results) => {
console.log("check rolename gettign below");
console.log(results);
if (results.Name == "Customer") {
console.log("User is Customer");
changeUserToSellerFlag = 1;
console.log("flag is :" + changeUserToSellerFlag);
} else if (results.Name == "Seller") {
console.log("User is Seller");
changeUserToSellerFlag = 0;
}
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
});
}
console.log("see flag changed here ", changeUserToSellerFlag);
if (changeUserToSellerFlag == 1) {
console.log("i am here");
//update userrole to seller only if user is not a seller earlier
updateUserRoleAfterSellerApproval(
req.userId,
req.roleId,
(err, results) => {
console.log("result details are bwlo");
console.log(results);
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
console.log("Update into UserRole Completed successfully");
},
);
} else {
console.log(
"User is already a seller and dont need to update userrole table",
);
}
console.log(sellerStatusName);
return res.status(200).json({
success: 1,
status: sellerStatusName,
});
},
);
},
};
Below is console output
Request body is below
{ sellerId: 122, sellerStatus: 2 }
see flag changed here 0
User is already a seller and dont need to update userrole table
Completed
check rolename gettign below
TextRow { Name: 'Customer', RoleId: 2 }
User is Customer
flag is :1
where "User is already a seller and dont need to update userrole table" is executed first before "flag is :1"
to me it looks as if you're treating asynchronous code as if it was synchronous. At the top of the function you are calling parts of the code that are asynchronous, like for example every database query is generally async call.
getRoleName(req.userId, (err, results) //i assume this is an async call
process will not wait for the above code to finish before proceeding forward with its execution because it is written synchronously. So next instructions that it will execute are:
console.log('see flag changed here ', changeUserToSellerFlag);//0
if(changeUserToSellerFlag == 1)//0 --> false
}else{console.log("User is already a seller and dont need to update userrole table");}//so these 3 orders are executed immediately.
after which the async call from (i assume)
getRoleName(req.userId, (err, results)
will have finished and the proper callback will be called.
as a potential solution:
I would either wait for any database call to finish before proceeding. You can use async - await call, other solutions are also usage of Promises and of course making a callback hell.
If we use callback because you are already using them it would look something like this:
updateUserSellerStatus(
req.body,
approvedByName,
approvedByEmail,
(err, results) => {
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
if (req.body.sellerStatus == 3) {
sellerStatusName = "Rejected";
} else if (req.body.sellerStatus == 2) {
sellerStatusName = "Completed";
} else if (req.body.sellerStatus == 1) {
sellerStatusName = "Pending";
}
//verify if user is a seller or not
if (req.userId) {
getRoleName(req.userId, (err, results) => {
console.log('check rolename gettign below');
console.log(results);
if (results.Name == "Customer") {
console.log("User is Customer");
changeUserToSellerFlag = 1;
console.log("flag is :" + changeUserToSellerFlag);
} else if (results.Name == "Seller") {
console.log("User is Seller");
changeUserToSellerFlag = 0;
}
console.log('see flag changed here ', changeUserToSellerFlag);
if (changeUserToSellerFlag == 1) {
console.log("i am here");
//update userrole to seller only if user is not a seller earlier
updateUserRoleAfterSellerApproval(
req.userId,
req.roleId,
(err, results) => {
console.log("result details are bwlo");
console.log(results);
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
console.log("Update into UserRole Completed successfully");
}
);
} else {
console.log("User is already a seller and dont need to update userrole table");
}
console.log(sellerStatusName);
return res.status(200).json({
success: 1,
status: sellerStatusName,
});
}
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
});
}
);
},
};
I just moved the code which was below the
console.log('see flag changed here ', changeUserToSellerFlag);
inside the first callback method.
I'd recommend refactoring the callback-hell asynchronicity to promises.
Happily, util.promisify in Node's util library makes it super easy to do that for functions that are callback-async.
You end up with something like this:
const { promisify } = require("util");
const { updateUserSellerStatus } = require("./seller.model.js");
const userid = require("../auth/token_validation.js");
const {
updateUserRoleAfterSellerApproval,
getRoleName,
} = require("../users/user.service.js");
const updateUserSellerStatusP = promisify(updateUserSellerStatus);
const getRoleNameP = promisify(getRoleName);
const updateUserRoleAfterSellerApprovalP = promisify(
updateUserRoleAfterSellerApproval,
);
async function sellerVerify(req) {
var sellerStatusName;
var changeUserToSellerFlag = 0; // this flag determines if user to seller update is needed or not
switch (req.body.sellerStatus) {
case 3:
sellerStatusName = "Rejected";
break;
case 2:
sellerStatusName = "Completed";
break;
case 1:
sellerStatusName = "Pending";
break;
}
const results = await updateUserSellerStatusP(
req.body,
req.fullName,
req.email,
);
if (!results) throw new Error("No results from UUSS");
//verify if user is a seller or not
if (req.userId) {
const roleName = await getRoleNameP(req.userId);
if (roleName.Name === "Customer") {
changeUserToSellerFlag = 1;
} else if (roleName.Name === "Seller") {
changeUserToSellerFlag = 0;
}
}
if (changeUserToSellerFlag) {
console.log("i am here");
//update userrole to seller only if user is not a seller earlier
const results = await updateUserRoleAfterSellerApprovalP(
req.userId,
req.roleId,
);
console.log(results);
if (!results) throw new Error("UURASP results missing");
console.log("Update into UserRole Completed successfully");
} else {
console.log(
"User is already a seller and dont need to update userrole table",
);
}
console.log(sellerStatusName);
return {
success: 1,
status: sellerStatusName,
};
}
module.exports = {
sellerVerify: async (req, res) => {
try {
const result = await sellerVerify(req);
return res.json(result);
} catch (err) {
console.error(err);
return res.status(500).json({
success: 0,
message: err,
});
}
},
};

cannot set headers after they are sent to the client when i use mongoose remove function

when i use this code
activecode.remove(err => {
return res.status(500).json("error message ")
});
get the error cannot set headers after they are sent to the client
when i remove the above code it works without error
this is my code
async activeUser(req, res, next) {
try {
const code = req.params.code;
const activecode = await ActiveCode.findOne({
code
}).gt("expire", new Date()).populate("user").limit(1).exec();
if (activecode) {
if (activecode.used) {
return res.status(400).json({
message: "از این لینک قبلا استفاده شده است"
})
} else {
activecode.used = true;
activecode.save(err => {
if (err) {
return res.status(500).json({
message: "خطایی در فعال سازی رخ داد"
})
};
});
if (activecode.user) {
activecode.user.isActive = true;
activecode.user.save(err => {
if (err) {
return res.status(500).json({
message: "خطایی در فعال سازی رخ داد"
})
};
});
const user = {
id: activecode.user.id,
name: activecode.user.name,
email: activecode.user.email,
isActive: activecode.user.isActive
}
activecode.remove(err => {
return res.status(500).json("خطایی در فعال سازی اکانت رخ داد ")
});
return res.status(200).json({
user
});
}
}
} else {
return res.status(400).json({
message: "چنین لینکی برای فعال سازی حساب وجود ندارد"
});
}
} catch (err) {
return res.status(500).json({
message: "خطایی در فعال سازی حساب رخ داده لطفا دوباره امتحان کنید"
});
}
}
any
res.status.json
used with return
what i do for solve this problem . where my code trying to send multiple responses
Because you already have an async function with try/catch so you don't need to use .save() and .remove() with callback. You just need to use await and let the catch handle error for you.
This may help:
async activeUser(req, res, next) {
try {
const code = req.params.code;
const activecode = await ActiveCode.findOne({
code
}).gt("expire", new Date()).populate("user").limit(1).exec();
if (activecode) {
if (activecode.used) {
return res.status(400).json({
message: "از این لینک قبلا استفاده شده است"
})
} else {
activecode.used = true;
await activecode.save();
if (activecode.user) {
activecode.user.isActive = true;
await activecode.user.save();
const user = {
id: activecode.user.id,
name: activecode.user.name,
email: activecode.user.email,
isActive: activecode.user.isActive
}
await activecode.remove();
return res.status(200).json({
user
});
}
}
} else {
return res.status(400).json({
message: "چنین لینکی برای فعال سازی حساب وجود ندارد"
});
}
} catch (err) {
return res.status(500).json({
message: "خطایی در فعال سازی حساب رخ داده لطفا دوباره امتحان کنید"
});
}
}
Change this part of your code:
activecode.remove(err => {
return res.status(500).json("خطایی در فعال سازی اکانت رخ داد ")
});
return res.status(200).json({
user
});
With
activecode.remove((err, data) => {
if (err) {
return res.status(500).json("خطایی در فعال سازی اکانت رخ داد ");
} else {
return res.status(200).json({user});
}
});
The problem here your request tries to send response twice, which is not allowed.
hope this helps :)
The situation is arising because you are trying to send the response for a particular request twice which is not allowed.
Also on side note,your request route doesnt gets finished when they encouter a response(res.status().json() or res.send()) it will continue to the parse to the end of the function and if while parsing they encounter another res.send() or res.status().json() they will throw the above error.
for example
app.get('/some_route',(req,res)=>{
if("condition")
res.send('something);
else
res.send('another thing');
})
app.get('/some_route',(req,res)=>{
if("condition")
res.send('something');
res.send("another something");
})
the first example is correct but the second one is not

NodeJS , how to send response during Promise .then?

I have the following code:
User.getConfByID(userID)
.then((item)=>{
if(item.length == 0){
res.status(400).json({error:"NO_USER_FOUND"})
}else{
if(item[0].token == token){
if((Math.abs(Date.now() - item[0].conf_iat)) > tokenValid){
res.status(401).json({error: "TOKEN_INVALID"})
}else{
return mariaDBTemplates.updateOneRowTemplate("User_confirmation", {confirmed:1}, "user_id", userID)
}
}else{
res.status(401).json({error: "TOKEN_NOT_SAME"})
}
}
})
.then(()=>{
res.status(200).json({success: "CONFIRMED"})
})
.catch((err)=>{
res.status(500).json({error: err.message})
})
You see I have different kinds of error messages with different kinds of status codes. When I run this code, it always gives me this warning:
Error: Can't set headers after they are sent
I think this is because i don't "break" the Promise after sending a response right?. But how can I solve this? Any suggestions?
Cheerio
your problem is with your promise chain. in your first .then, you always set the response with res, but the next .then in the chain tries to set the response again. Note that not returning anything from a promise is the same as return Promise.resolve(undefined);.
here's how I would do it:
User.getConfByID(userID)
.then((item) => {
if(item.length == 0)
return { statusCode: 400, body: { error: "NO_USER_FOUND" } };
else {
if(item[0].token == token) {
if((Math.abs(Date.now() - item[0].conf_iat)) > tokenValid)
return { statusCode: 401, body: { error: "TOKEN_INVALID" } };
else {
//not sure what this returns, but it looks like this is
//what you're trying to return the 200 for
mariaDBTemplates.updateOneRowTemplate("User_confirmation", { confirmed: 1 }, "user_id", userID);
return { statusCode: 200, body: { success: "CONFIRMED" } };
}
} else
return { statusCode: 401, body: { error: "TOKEN_NOT_SAME" } };
}
})
.then((result) => {
res.status(result.statusCode).json(result.body);
})
.catch((err) => {
res.status(500).json({ error: err.message });
});
Also note that returning a value from a promise is the same as returning Promise.resolve(value);, and will continue the promise chain.

Parse Server Cloud Code - Update OR Create object

I am using Parse Server on AWS and mLab with great success, except for my Cloud Code. The main issue is surrounding my previous code for Create OR Update an object. I used to do this by querying for a user pointer on the Favourites class. If a row contains a user pointer then I need to update its content, if it doesn't exist a row needs to be created.
Old Parse.com Code
Parse.Cloud.define("saveFavourites", function(request, response) {
console.log(request.params.favourites);
var Favourites = Parse.Object.extend("Favourites");
var query = new Parse.Query("Favourites");
query.equalTo('user', request.user);
query.first({
success: function(results) {
console.log(JSON.stringify(results));
console.log(results)
if (results === undefined) {
var favourites = new Favourites();
favourites.save({
user: request.user,
favourites: request.params.favourites
}, {
success: function(favourites) {
// The object was saved successfully.
},
error: function(favourites, error) {
// The save failed.
// error is a Parse.Error with an error code and message.
}
});
} else {
results.set("favourites", request.params.favourites);
results.set("userId", request.user.id);
results.save();
}
response.success(results);
},
error: function(error) {
error.message("favourites lookup failed");
}
});
});
New Parse Server Code
Parse.Cloud.define("saveFavourites", function(request, response) {
console.log('user is : ' + JSON.stringify(request.user));
var Favourites = Parse.Object.extend("Favourites");
var query = new Parse.Query("Favourites");
query.equalTo("user", request.user);
query.first({
useMasterKey: true
}, {
success: function(results) {
if (results && results.length > 0) {
console.log('running found');
favourites.set("favourites", request.params.favourites);
favourites.set("userId", request.user.id);
favourites.save();
response.success();
} else {
var favourites = new Favourites();
favourites.set("user", request.user);
favourites.set("favourites", request.params.favourites);
favourites.set("userId", request.user.id);
favourites.save();
response.success();
}
},
error: function(error) {
console.log(error.message);
}
});
});
Do not response unless callback finished. Set response.error on each Parse requests error.
Parse.Cloud.define("saveFavourites", function(request, response) {
console.log(request.params.favourites);
var Favourites = Parse.Object.extend("Favourites");
var query = new Parse.Query("Favourites");
query.equalTo('user', request.user);
query.first({
//is this query need masterKey?
useMasterKey: true,
success: function(results) {
console.log(JSON.stringify(results));
console.log(results)
if (results === undefined) {
var favourites = new Favourites();
favourites.save({
user: request.user,
favourites: request.params.favourites
}, {
success: function(favourites) {
// The object was saved successfully.
response.success(results);
},
error: function(favourites, error) {
// The save failed.
// error is a Parse.Error with an error code and message.
response.error(error);
}
});
} else {
results.set("favourites", request.params.favourites);
results.set("userId", request.user.id);
results.save(null, { useMasterKey: true }).then(response.success, response.error);
}
},
error: function(error) {
error.message("favourites lookup failed");
response.error(error);
}
});
});

How to return an array from ExpressJS?

Could someone explain how this is happening? An array from Express is being destroyed before it is returned. In the example below, I am successfully populating the resData.user.apps array and can see this via the server's console log. However, when the resData object is returned the array is empty:
// Build the response
var resData = {
success: true,
user: {
email: newUserItem.email,
apps: []
}
};
// Add any default applications
Application.find({ isDefault: true, isDeleted: false }, function(err, defaultApps){
if (err){
console.log(err);
return res.status(500).send({ message: 'Failure loading default applications.' });
} else {
if (defaultApps.length < 1){
console.log('No default apps');
} else {
defaultApps.forEach(function(defaultApp){
var app = {
name: defaultApp.formalName,
url: defaultApp.url,
def: true
};
console.log(app);
resData.user.apps.push(app);
console.log('Sanity: ' + JSON.stringify(resData));
});
}
}
});
return res.send(resData);
The problem here is that the find is async so you are writing back the response before the call has completed. Move return res.send(resData); into the find callback.
Application.find({ isDefault: true, isDeleted: false }, function(err, defaultApps){
if (err){
console.log(err);
return res.status(500).send({ message: 'Failure loading default applications.' });
} else {
if (defaultApps.length < 1){
console.log('No default apps');
} else {
defaultApps.forEach(function(defaultApp){
var app = {
name: defaultApp.formalName,
url: defaultApp.url,
def: true
};
console.log(app);
resData.user.apps.push(app);
console.log('Sanity: ' + JSON.stringify(resData));
});
}
res.send(resData);
}
});

Resources