I am uploading the excel sheet in DB with the help of Nodejs, I am unable to authenticate and return the error as already exist the userid
when the item.USER_ID
already exists in DB. my server goes crash and returns an error as Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Please help in the code how I fix this issue and make it, If the item.USER_ID
already exists return error else insert.
var XLSX = require("xlsx");
const fs = require("fs");
try {
const transaction = await con.transaction();
var workbook = XLSX.readFile("myfile.xlsx");
let json_data = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet1);
let count = 0;
json_data.map(async (item) => {
let stmt1 = await con.query("SELECT * FROM `table` WHERE `user_id` = :userid", { replacements: { userid: item.USER_ID }, type: con.QueryTypes.SELECT });
if (stmt1.length > 0) {
await transaction.rollback();
return res.json({ message: "already exist the userid" });
} else {
let stmt2 = await con.query("INSERT INTO `table` (`user_id` , `user_name`) VALUES ( :user_id , :user_name)", {
replacements: {
user_id: item.USER_ID,
user_name: item.USER_NAME,
},
type: con.QueryTypes.INSERT,
transaction: transaction,
});
count++;
if (count == json_data.length) {
await transaction.commit();
return res.json({ message: "file uploaded successfully.." });
}
}
});
} catch (err) {
await transaction.rollback();
return res.json({ code: 500, message: { msg: "SQL ERROR" }, error: err.stack, status: "error" });
}
A possible clue is from https://stackoverflow.com/questions/26307920/res-json-cant-set-headers-after-they-are-sent where they say that res.json results in sending a response to the client, so if you are also attempting to send a response from some other part of the code then you will be attempting to send two sets of responses, resulting in that error message.
I understand but I don’t have any other idea to implement this function that validates the data. I also used for loop but not worked…
please help to create this function as expected.
for (const value of json_data) {
let stmt1 = await con.query(
"SELECT * FROM `table` WHERE `user_id` = :userid",
{ replacements: { userid: item.USER_ID }, type: con.QueryTypes.SELECT }
);
if (stmt1.length > 0) {
await transaction.rollback();
return res.json({ message: "already exist the userid" });
} else {
let stmt2 = await con.query(
"INSERT INTO `table` (`user_id` , `user_name`) VALUES ( :user_id , :user_name)",
{
replacements: {
user_id: item.USER_ID,
user_name: item.USER_NAME,
},
type: con.QueryTypes.INSERT,
transaction: transaction,
}
);
count++;
if (count == json_data.length) {
await transaction.commit();
return res.json({ message: "file uploaded successfully.." });
}
}
}
Just a guess cause I do not understand the whole picture but this should work…
for (const value of json_data)
{
let stmt1 = await con.query("SELECT * FROM `table` WHERE `user_id` = :userid",
{
replacements: { userid: item.USER_ID }, type: con.QueryTypes.SELECT
});
if (stmt1.length == 0)
{
let stmt2 = await con.query( "INSERT INTO `table` (`user_id` , `user_name`) VALUES ( :user_id , :user_name)",
{
replacements:
{
user_id: item.USER_ID,
user_name: item.USER_NAME,
},
type: con.QueryTypes.INSERT,
transaction: transaction,
});
}
}
return res.json({ message: "file uploaded successfully.." });
1 Like
but how I return res.json({ message: "already exist the userid" })
if already exist ?
Without seeing the rest of your code, this will be hard to diagnose.
(Why do I say we’re not seeing it all? Nothing defines res
on line 14.)
Do you do anything with res
prior to this codeblock?
If your json contains multiple users you need a loop to loop through the users. In that Case 1 or more users can exists or even not. So you can never return „user already exists“. In that Case you can, for example, add the users name to a string and at the end return the string with all names.
If you json only contains one user, you do not need a loop and you can return if the user exists or not
1 Like
This is all very much theory, but Promise.all came to mind.
// updateUser as a standalone function
const updateUser = async function(user, transaction) {
const foundUser = await con.query(
"SELECT * FROM `table` WHERE `user_id` = :userid",
{
replacements: { userid: user.USER_ID },
type: con.QueryTypes.SELECT
}
)
if (foundUser === 0) {
await con.query(
"INSERT INTO `table` (`user_id` , `user_name`) VALUES ( :user_id , :user_name)",
{
transaction,
replacements: {
user_id: user.USER_ID,
user_name: user.USER_NAME,
},
type: con.QueryTypes.INSERT,
}
);
}
};
// then maybe a function that updates all users
const updateUsers = async function(workbook) {
try {
const transaction = await con.transaction();
const workbook = XLSX.readFile(workbook);
const users = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet1);
// process all the asynchronous query operations first
await Promise.all(users.map((user) => updateUser(user, transaction)))
await transaction.commit();
return res.json({ message: "file uploaded successfully.." });
} catch (err) {
await transaction.rollback();
return res.json({
code: 500,
message: { msg: "SQL ERROR" },
error: err.stack, status: "error" }
);
}
}
updateUsers ('myfile.xlsx')
Working through this, I came to the same conclusion as @Thallius. It seemed logical that you return either a successful file upload or an error.
I guess it could be altered to return a log of users that were successfully and unsuccessfully added.
1 Like
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.