forEach not working as expected in NodeJs – JavaScript – SitePoint Forums


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.



Source link

Share

Leave a Reply

Your email address will not be published. Required fields are marked *