NodeJS Async Await Insert Data to Database and Google API - node.js

I'm working as API Backend with NodeJS. In case, when I insert 1 row the data will automatically updated to DB and Goolge Sheet API.
I already create the code in controller but I want to make it as Async Await, to makesure data inserted to DB first.
Here is my code:
createUser: (req, res, next) => {
bcrypt.genSalt(Number(env.SALTROUNDS_USER), (err, resultSalt) => {
bcrypt.hash(req.body.password, resultSalt, (err, hash) => {
doc.useServiceAccountAuth(creds, function(err){
// regis to db
let datauser = new modelsUsers({
email: req.body.email,
name: req.body.name,
password: hash,
phone_number: req.body.phone_number
});
//regis to GoogleSheetApi
doc.addRow(1,{
timestamps: tgl_ob,
name: req.body.name,
email: req.body.email,
phone_number: req.body.phone_number
},function(err){
if(err){
console.log(err); //errors
}
});
if(err){
console.log(err); //success
}
datauser.save((err, result) => {
if (result) res.send(result);
else res.send(err);
});
})
});
});
},

You can use util to make callbacks to promise
const GoogleSpreadsheet = require('google-spreadsheet');
const { promisify } = require('util')
const doc = new GoogleSpreadsheet(process.env.sheetid);
const creds = require('./../creds.json') // JSON file you can get from serviceaccount
createUser: (req, res, next) => {
bcrypt.genSalt(Number(env.SALTROUNDS_USER), (err, resultSalt) => {
bcrypt.hash(req.body.password, resultSalt, async (err, hash) => {
// you can also convert genSalt, salt to Promis
await promisify(doc.useServiceAccountAuth)(creds)
const info = await promisify(doc.getInfo)();
const sheets = info.worksheets;
let datauser = new modelsUsers({
email: req.body.email,
name: req.body.name,
password: hash,
phone_number: req.body.phone_number
});
const data = {
timestamps: tgl_ob,
name: req.body.name,
email: req.body.email,
phone_number: req.body.phone_number
}
// as you need to save to DB first and then add ROW to sheet
datauser.save(async (err, result) => {
if (result) {
await addRows(sheets, 1, data) // you can wrap in try catch for error handling
res.send(result);
}
else res.send(err);
});
})
});
}
function addRows(sheet, index, data) {
return new Promise((resolve, reject) => {
sheet[index].addRow(data, (err, row) => {
if (err) return reject(err)
resolve(row)
})
})
}

Related

TypeError: Cannot read properties of undefined (reading 'buffer')

In the front-end use form-data to send a post/put method to save data and edit data in the server. In the front-end have a problem with the image field. when new data is added. the new data will be saved. but when they try to edit data, the data changes made will not be saved, only saved if the image field is changed. (this problem only occurs in ios).
in IOS when they try to update data without changing the image field server will be crashed
router.put("/:id", authenticate, async (req, res) => {
uploads(req, res, function (err) {
if (err instanceof multer.MulterError) {
return send(res, RESPONSE.FILE_TOO_LARGE);
} else if (err) {
return send(res, RESPONSE.UNKNOWN_ERROR);
}
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: `uploads/${uuid()}`,
Body: req.file.buffer,
};
s3.upload(params, async (error, data) => {
if (error) {
send(res, RESPONSE.UNKNOWN_ERROR);
}
try {
const id = req.params.id;
const updatedData = {
first_name: req.body.first_name,
last_name: req.body.last_name,
phone: req.body.phone,
email: req.body.email,
image: data.Key,
};
const options = { new: true };
await SomeModel.findByIdAndUpdate(id.trim(), updatedData, options);
return send(res, RESPONSE.SUCCESS);
} catch (err) {
return res.status(400).send(err.message);
}
});
Sounds like you should only do the S3 upload and set image if req.file is present
router.put("/:id", authenticate, (req, res) => {
uploads(req, res, async (err) => {
if (err instanceof multer.MulterError) {
return send(res, RESPONSE.FILE_TOO_LARGE);
} else if (err) {
return send(res, RESPONSE.UNKNOWN_ERROR);
}
const id = req.params.id;
const updatedData = {
first_name: req.body.first_name,
last_name: req.body.last_name,
phone: req.body.phone,
email: req.body.email,
};
try {
if (req.file) {
const { Key } = await s3
.upload({
Bucket: process.env.AWS_BUCKET_NAME,
Key: `uploads/${uuid()}`,
Body: req.file.buffer,
})
.promise();
updatedData.image = Key;
}
await SomeModel.findByIdAndUpdate(id.trim(), updatedData, { new: true });
return send(res, RESPONSE.SUCCESS);
} catch (err) {
return res.status(400).send(err.message);
}
});
});

I Need To Avoid The Duplicate Entries In DataBase

i am trying to add some data inside my MongoDB database, but i am not able to remove duplicate entries.
please help me to do so.
i am using node js and mongoose.
app.post('/', function (req, res) {
const newUser = new Newsletter ({
fname: req.body.fname,
lname: req.body.lname,
message: req.body.message,
email: req.body.email
});
newUser.save(function (err) {
if (!err) {
res.render("success");
} else {
const errCode = res.statusCode;
res.render("failure", { errStatusCode: errCode });
}
})
})

How to send maltipart/formdata from react to nodejs?

Hi I am new in MERN development world. I am trying develop my first MERN APP, till text input from browser I have created. Now I am stucked at the file input.
File field is working fine at frontend but in api the file field is empty but rest of the fields are working well...
In browser before api call photo/ file is there but in the api req.body or req.file no data.
I have used multer which is working fine.
Please help me, I trapped here.
Frontend Code
export const register = ({ name, email, password, password1, photo }) => (dispatch) => {
// Request body
const body = { name, email, password, password1, photo };
/*console.log(photo); //gives the desired output...*/
axios.post('/api/users/register', body)
.then(function (res) {
dispatch(returnStatus(res.data, res.status, 'REGISTER_SUCCESS'));
dispatch({ type: IS_LOADING })
})
.catch(function (err) {
dispatch(returnStatus(err.response.data, err.response.status, 'REGISTER_FAIL'))
dispatch({
type: REGISTER_FAIL
});
dispatch({ type: IS_LOADING })
});
};
Serverside code
exports.registerUser = (upload.single("photo"), (req, res) => {
const { name, email, password, password1 } = req.body;
console.log(req.file,req.body);
if(password != password1) return res.status(400).json("Passwords missmacth.");
const result = registerSchema.validate({ name, email, password});
if(!result.error) {
// Check for existing user
User.findOne({ email: email }).then((user) => {
if (user) return res.status(400).json("User already exists");
//New User created
const newUser = new User({
name,
email,
password,
password1
});
//Password hashing
bcrypt.genSalt(12, (err, salt) =>
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
bcrypt.hash(newUser.password1, salt, (err, hash) => {
if (err) throw err;
newUser.password1 = hash;
// Save user
newUser
.save()
.then(
res.json("Successfully Registered")
)
.catch((err) => console.log(err));
})
})
);
});
} else {
res.status(422).json(result.error.details[0].message);
}
});

How to use async await with another API's implementation code

I have a user register function which is using async/await and I need to implement some code from another API. When I try to integrate it I get an error that I can't use await outside an async function.
exports.register = async (req, res) => {
// some logic here
nexmo.verify.request(
{
number: formattedMobile,
brand: "My Brand",
code_length: "4",
},
(err, result) => {
if (err) {
// If there was an error, return it to the client
return res.status(500).send(err.error_text);
}
// Otherwise, send back the request id. This data is integral to the next step
const requestId = result.request_id;
const salt = await bcrypt.genSalt(12);
const hashedPassword = await bcrypt.hash(password, salt);
const createdUser = new User({
name: name,
email: email,
mobile: formattedMobile,
password: hashedPassword,
});
try {
await createdUser.save();
res.status(200).send({ user: createdUser._id, otp: requestId });
} catch (err) {
res.status(500).send(err);
}
}
You need to make the callback function async, and most likely wrap the entire code in a try catch block to handle errors.
async (err, result) => {
if (err) {
// If there was an error, return it to the client
return res.status(500).send(err.error_text);
}
try {
// Otherwise, send back the request id. This data is integral to the next step
const requestId = result.request_id;
const salt = await bcrypt.genSalt(12);
const hashedPassword = await bcrypt.hash(password, salt);
const createdUser = new User({
name: name,
email: email,
mobile: formattedMobile,
password: hashedPassword,
});
try {
await createdUser.save();
res.status(200).send({ user: createdUser._id, otp: requestId });
} catch (err) {
res.status(500).send(err);
}
} catch(err) {
console.log(err);//do whatever error handling here
}
}

having problem with Node.js and ES6 promise

this is my piece of code:
i declared a variable(newSeller) and i expect to use it in the process
let newSeller = '';
if (req.body.selectSeller == '') {
User.findOne({email: req.body.sellerEmail}).then(userEx => {
if (!userEx) {
const newUser = new User({
firstName: req.body.sellerName,
lastName: req.body.sellerLastName,
title: req.body.sellerTitle,
phoneNumber: req.body.sellerPhNum,
email: req.body.sellerEmail,
password: req.body.password,
address: req.body.sellerAddress
});
bcrypt.genSalt(10, (err, salt)=>{
bcrypt.hash(newUser.password, salt, (err, hash)=>{
newUser.password = hash;
});
});
newUser.save().then(savedSeller => {
newSeller = savedSeller.id;
});
} else if (userEx) {
req.flash('error_message', 'this email already exists. try another one')
res.redirect('/admin/invoice/incoming');
}
});
} else {
newSeller = req.body.selectSeller;
}
this piece of code actually saves the expected document successfully but when i assign the variable (newSeller) to the value of ES6 promise (after then() ) it doesn't work!
could you please help me with this?
how can i fetch the saved user values?
Basically you are using async and sync functions together in various places which messes up everything. Basically you cannot use sync functions if you use even one async function in the entire module. But then again in async functions, Try to use promise based syntaxes or async-await
Assuming you are using the code in some express route here is how you can simplify the code(commented for understanding):
app.post('/someroute', async (req, res) => { //<<-Async handler
let newSeller = '';
if (req.body.selectSeller == '') {
try { //<<--need to catch `async-await` errors
const userEx = await User.findOne({ email: req.body.sellerEmail });//<<awaiting the result
if (!userEx) {
const newUser = new User({
firstName: req.body.sellerName,
lastName: req.body.sellerLastName,
title: req.body.sellerTitle,
phoneNumber: req.body.sellerPhNum,
email: req.body.sellerEmail,
password: req.body.password,
address: req.body.sellerAddress
});
const salt = await bcrypt.genSalt(10); // await
const hash = await bcrypt.hash(newUser.password, salt);// await
newUser.password = hash;
const savedSeller = await newUser.save(); //await
newSeller = savedSeller.id;
} else {
req.flash('error_message', 'this email already exists. try another one')
res.redirect('/admin/invoice/incoming');
}
} catch (err) { //<<--if there is an error
req.flash(...something...)
res.redirect(...somewhere...);
}
} else {
newSeller = req.body.selectSeller;
}
//do something with newSeller
})

Resources