Hi I finished the project recently and noticed that in a lists collection creates duplicates the first time saving an item in MongoDb. The first item created is always a duplicate. Please see screenshot attached. Is there any particular reasonenter image description here why this is case?
somthing like this should work:
app.get('/:customListName', async (req, res) => {
try {
let foundList = await List.findOne({ name: req.params.customListName });
if (!foundList) {
const foundList = new List({
name: req.params.customListName,
item: defualtItems
});
await foundList.save();
res.redirect(`/${req.params.customListName}`);
} else {
res.render('list', {
listTitle: foundList.name,
newListItems: foundList.items
});
}
} catch (error) {
res.status(500).json({ error: error.message });
}
});
I recommend you to read more about async await when writing and saving to database, and about the usage of try-catch blocks when handling errors.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
Related
I have to handle a message coming from application on form filling. if it comes have to close the alert window using (X)button.
problem is I'm not able to close it. directly close (.click()) works fine.
but on condition when i say if alert is present then only close it scenario is not working. Any help is appreciated
try {
var Alert1 = element(by.xpath("//h2[text()='Job Role']/parent::div/following-sibling::div//span"));
Alert1.isPresent().then(async function(res) {
if (res) {
Alert1.click();
}
})
} catch (err) {
console.log(err)
}
})
it('async test case', async () => {
var Alert1 = element(by.xpath("//h2[text()='Job Role']/parent::div/following-sibling::div//span"));
if (await Alert1.isPresent()) {
await Alert1.click();
}
})
simple, readable and robust if you avoid .then
I have been trying to reduce my NextJS bundle size by moving my XLSX parsing to an API route. It uses the npm xlsx (sheetjs) package, and extracts JSON from a selected XLSX.
What I am doing in the frontend is
let res;
let formData = new FormData();
formData.append("file", e.target.files[0]);
try {
res = await axios.post("/api/importExcel", formData);
} catch (e) {
createCriticalError(
"Critical error during file reading from uploaded file!"
);
}
On the API route I am unable to to read the file using XLSX.read()
I believe NextJS uses body-parser on the incoming requests but I am unable to convert the incoming data to an array buffer or any readable format for XLSX.
Do you have any suggestions about how to approach this issue?
I tried multiple solutions, the most viable seemed this, but it still does not work
export default async function handler(req, res) {
console.log(req.body);
let arr;
let file = req.body;
let contentBuffer = await new Response(file).arrayBuffer();
try {
var data = new Uint8Array(contentBuffer);
var workbook = XLSX.read(data, { type: "array" });
var sheet = workbook.Sheets[workbook.SheetNames[0]];
arr = XLSX.utils.sheet_to_json(sheet);
} catch (e) {
console.error("Error while reading the excel file");
console.log({ ...e });
res.status(500).json({ err: e });
}
res.status(200).json(arr);
}
Since you're uploading a file, you should start by disabling the body parser to consume the body as a stream.
I would also recommend using a third-party library like formidable to handle and parse the form data. You'll then be able to read the file using XLSX.read() and convert it to JSON.
import XLSX from "xlsx";
import formidable from "formidable";
// Disable `bodyParser` to consume as stream
export const config = {
api: {
bodyParser: false
}
};
export default async function handler(req, res) {
const form = new formidable.IncomingForm();
try {
// Promisified `form.parse`
const jsonData = await new Promise(function (resolve, reject) {
form.parse(req, async (err, fields, files) => {
if (err) {
reject(err);
return;
}
try {
const workbook = XLSX.readFile(files.file.path);
const sheet = workbook.Sheets[workbook.SheetNames[0]];
const jsonSheet = XLSX.utils.sheet_to_json(sheet);
resolve(jsonSheet);
} catch (err) {
reject(err);
}
});
});
return res.status(200).json(jsonData);
} catch (err) {
console.error("Error while parsing the form", err);
return res.status(500).json({ error: err });
}
}
For some reason, the function .save() isn't saving my documents on MongoDB. All seem right and the first two registers work and update successfully, but my third register 'specialBanner' doesn't work.
When I console log service it doesn't show as part of the special object, although when I console special.specialBanner it is there.
Has anyone experienced something like this before?
Thanks for your help :)
const updateSpecial = async (req, res, next) => {
const { title, description, specialBanner } = req.body;
let special;
try {
special = await Special.findById(specialId);
} catch (err) {
const error = new HttpError(
"Something went wrong, could not update special.",
500
);
return next(error);
}
if (title) {
special.title = title;
}
if (description) {
special.description = description;
}
if (specialBanner) {
special.specialBanner = specialBanner;
}
try {
//Here if I check 'special I get all the right inputs, but the 'specialBanner'.
special = await special.save();
} catch (err) {
const error = new HttpError(
"Something went wrong, could not update special.",
500
);
return next(error);
}
res.status(200).json({ special: special.toObject({ getters: true }) });
};
I assume you are using mongoose and, Special is a collection.
Replace the line
special = await Special.findById(specialId)
with
special = await Special.findById(specialId).exec()
var userSchema = mongoose.Schema({
username: { type: String},
email: String,
password: String,
tasks: [String]
});
I want to create a new user document only if there is no another user with the same name.
What the best way to do that?
this is my implementation currently :
router.post('/', async function(req, res, next) {
use let user= await User.findOne({ name: req.body.name})
if (user) {
if (req.body.name == user.name) {
// return new Error("User exists!"));
}
User.create(req.body, function (err, newuser) {
if (err) {
console.log(err);
return next(err);
}
res.json(newuser);
});
}
Another question about mongoDB collections:
Should I open new collection ( and schema) for 'task' property?
It has only 1 field - the task itself in type string.
Your current implementation is the way to go, you find the user, if none is found, you create a new one.
I refactored your code a little bit, here's how it would look like:
router.post('/', async function (req, res, next) {
try {
const user = await User.findOne({ name: req.body.name });
if (user) {
return res.json(user);
}
const newUser = await User.create(req.body);
return res.json(newUser);
} catch (err) {
console.log(err);
return next(err);
}
});
As to your second question, if you're sure that the task will always be a simple string and you won't need more data in there, it's better to keep it embedded within the document.
It's likely that you'll need to extend functionalities for tasks, and add more data such as a status, deadline, maybe subtasks, in which case it's better to separate it in a different collection.
This series of articles is probably a good place to quickly learn a rule of thumb on how to design your schemas.
Ok, I've got the following in one of my controllers:
User.find({email: 'email#example.com'}).then(function (user) {
user[0].field = 'new_value';
user[0].field_2 = 'new_value';
console.log(user[0], 'before saving');
user[0].save();
console.log(user[0], 'after saving');
});
If I console user[0] at this stage I can see the updated fields. However the changes were not saved to the db. If I do the following:
User.find({email: 'email#example.com'}).then(function (user) {
user[0].field = 'new_value';
user[0].field_2 = 'new_value';
user[0].save();
User.find(user[0].id).then(function (updateduser) {
console.log(updateduser[0])
});
});
The updateduser does not have the updated fields... Why is that? How can should I proceed in this case?
Actually
user[0].save();
will return a promise like you have done for User.find().then();
user[0].save() is an asynchronous call so the next call to find the user will run even though the user[0] is not updated in the database.
so place the second find command inside the then of save() function and you will get the updated user.
user[0].save().then(function(err){
User.find(user[0].id).then(function (updateduser) {
console.log(updateduser[0])
});
}))
Why you not use updated() method?
User.find({ email: 'email#example.com' })
.then(function(user) {
if (!user) return res.notFound();
User.update({ eamil: 'eamil#example.com' }, {
field: 'new_value',
field_2: 'new_value'
})
.then(function(updated_user) {
console.log(updated_user);
return res.ok();
})
.catch(function(err) {
sails.log.error(err);
return res.serverError();
});
})
.catch(function(err) {
sails.log.error(err);
return res.serverError();
});
First of all, you want to update only one user data because you are using user[0](I think).
So it is easy to use findOne().
Simple code
User
.findOne({email: 'email#example.com'})
.exec(function(err,user){
if(err || !user) {
//handle here
}
else {
user.key1 = 'new_value';
user.key2 = 'new_value';
user.save(function(err){
if(err){
//handle error
}
console.log('updatedUser',user)
})
}
})
Thank you.