Nodejs express API 500 internal server error when remove a semicolon ; - node.js

I've no habit to use semicolon ; in javascript code. This is my API but this is not working. Here response showing 500 Internal Server Error
router.post('/addRows', function (req, res) {
const saveData = []
[1,2,3,4,5,6,7,8,9,10].map((i) => {
console.log(i)
saveData.push(i)
if (saveData.length === 10) {
res.status(200).json({'data': saveData});
}
})
})
but If I add semicolon ; after 2nd line then this code is working. Here response showing 200 OK
router.post('/addRows', function (req, res) {
const saveData = [];
[1,2,3,4,5,6,7,8,9,10].map((i) => {
console.log(i)
saveData.push(i)
if (saveData.length === 10) {
res.status(200).json({'data': saveData});
}
})
})
What is issue. Please describe

You are experiencing one of the issues with automatic semicolon insertion, the feature of JavaScript that allows semicolons to be "optional".
In your case, when you miss out the semicolon after the array assignment, the array literal on the following line is being interpreted as a reference to an element within the array, which is of course undefined. You can read your code as:
router.post('/addRows', function (req, res) {
const saveData = [][1,2,3,4,5,6,7,8,9,10].map((i) => {
console.log(i)
saveData.push(i)
if (saveData.length === 10) {
res.status(200).json({'data': saveData});
}
})
})
That may not look valid but it is - the second array literal is being parsed as a property lookup containing an expression with comma ("grouping") operators. The comma operator returns its final operand, so you can simplify the above:
router.post('/addRows', function (req, res) {
const saveData = [][10].map((i) => {
console.log(i)
saveData.push(i)
if (saveData.length === 10) {
res.status(200).json({'data': saveData});
}
})
})
When you add the semicolon you remove the ambiguity and cause the second array literal to be parsed as an array literal rather than a property accessor.

If the ‘;’ is missed, your code will look like:
const saveData = [][1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(...)
it is going to access element from the empty array [], this code is equals to below:
const saveData = [][10].map(...)
obviously the 10th index of an empty array is undefined, so you will get TypeError: Cannot read property 'map' of undefined
Update:
Here are posts on this topic:
Why I Prefer To Use Semicolon In JavaScript
An Open Letter to JavaScript Leaders Regarding No Semicolons

Related

How to flatten and reduce array with objects to comma separated strings in javascript (ionic | Angular | NodeJS | MongoDB)

I have this array from an API:
let passions = [
{_id: "60a1557f0b4f226732c4597c",name: "Netflix"},
{_id: "60a1557f0b4f226732c4597b",name: "Movies"}
]
I would like to return exactly the following array:
['60a1557f0b4f226732c4597c', '60a1557f0b4f226732c4597b']
My code:
for(var key in passions){
return key._id
}
A simple map function should be enough to fix this issue for you.
const extractedIds = passions.map((e) => e._id);
The .map function applies that given function (in this case the function is (e) => e.["_id"]) to each element of your array and returns an array of the results. This means that it's going to return out a new array in the way you're hoping.
Live repl of this in action
const passionIDs = passions.reduce((acc, next) => {
acc.push(next._id);
return acc;
}, []);
checkout reduce function in Javascript

Can I have an if statement inside a map object to handle null values?

So i'm doing some web scraping of a bunch of products on a page & my code works fine as long as the elements are there, though sometimes when a product is out of stock and an element isn't present on a page I get the following error.
I've tried to put some kind of "If statement" inside the map object though can't get it to work.
//This code works if all the elements are present on the page
const productsOnPage = await page.$$eval('.tile-product', as => as.map(productContainer => ({
productTitle: productContainer.querySelector('h3').innerText.trim(),
}))
);
//I want something like this to handle the null values
const productsOnPage = await page.$$eval('.tile-product', as => as.map(productContainer => ({
if ( productContainer.querySelector('h3').innerText.length <= 0 || null ) {
productTitle: productContainer.querySelector('h3').innerText.trim(),
}
else {
productTitle: '',
}
}))
);
If null I expect:
productTitle: "";
but i'm getting:
Error: Evaluation failed: TypeError: Cannot read property 'innerText' of null
You can use ternary operator, E.g
const productsOnPage = await page.$$eval('.tile-product', as => as.map(productContainer => ({
productTitle: productContainer.querySelector('h3') ? productContainer.querySelector('h3').innerText.trim() : '';
}))
);
People already answered with the correct solution. But I believe an explanation is needed. On your if statement productContainer.querySelector('h3').innerText.length you're checking the length of the innerText property from querySelector('h3').
But you must verify if the
querySelector('h3') exists before reading its properties.

Cannot read property 'map' of undefined with promise all

I was initially just running one query in node.js but I now need two sets of data so I ran two queries and used Promise.all like this:
Promise.all([products, subcats]);
res.status(200).json({
products,
subcats
});
In React I have:
class ProductList extends Component {
state = {
products: []
};
async componentDidMount() {
const catslug = this.props.match.params.catslug;
const { data: products } = await getCatProducts(catslug);
this.setState({ products: products });
}
When I was only running the one query I was running this without any issue:
this.state.products.map(product => (
Now because I have the 2 queries I need to change it to:
this.state.products.products.map(product => (
But as soon as I do that I get the error:
Cannot read property 'map' of undefined
So, I changed it to this and now it works with no errors:
{this.state.products.products &&
this.state.products.products.map(product => (
My question is why did it work before without having to put in the ... && bit but now I have to use it with the Promise.all in node.js?
It's because of the initial shape of your state
state = {
products: []
};
You see this.state.products is already defined as an array, so it can be mapped over (despite being empty). However this.products.products is NOT an array, it is undefined, so trying to map will return the error you are seeing. The line you have entered
{this.state.products.products &&
this.state.products.products.map(product => (
checks that the array exists before attempting to map it (which wont evaluate to true until your async code finishes, and then the array is defined).
An alternative fix would be to set your initial state shape to match your final state shape. i.e
state ={
products:{
products:[]
}
};
Or if you don't want the nested products property you can change
async componentDidMount() {
const catslug = this.props.match.params.catslug;
const { data } = await getCatProducts(catslug);
this.setState({ products: data.products });
}
and return to your old this.state.products.map()
The issue is in the following line:
const { data: products } = await getCatProducts(catslug);
If I understand correctly, when you were sending one value, you were sending it like:
res.status(200).json(products); // an array
But now you are sending an object, which further contains 2 arrays products and subcats.
What you have 2 do is add below changes to make it work:
const obj = await getCatProducts(catslug);
const products = obj.products
const subcats = obj.subcats

Syntax Problem in Parameterized Query Using pg-promise and node.js

I've been working on a project with nodejs and pg-promise. Couldn't quite figure out how to implement parameterized query. Here how my code looks like:
// let's say we have an array
var hex = new Array;
hex = [[0, 1, 2, 'string1', 3, 'string2'],[4, 5, 6, 'string3', 7, 'string4']];
//lets assume db is initialized with correct parameters and we have a for loop
for (var i=0; i<hex.length; i++){
db.tx(t => {
return t.batch([
t.none('INSERT INTO x (lat, long, name) VALUES ($1[$2][0], $1[$2][1],
$1[$2][4];)',[hex,i]),
t.none('DELETE FROM x WHERE name='y'; ')];
)}
.then(data => {})
.catch(error => {
console.log('ERROR:', error);
});
)
}
My guess is that I'm not coding in right syntax especially in
t.none('INSERT INTO x (lat, long, name) VALUES ($1[$2][0], $1[$2][1], $1[$2][4];)',[hex,i]
I've read about the difference between passing arrays and parameters-functions in Vitaly's documentation. But couldn't merge them together since I'm guessing I need them both.
What am I doing wrong here?
EDIT: btw I'm getting syntax error near '['.
Thanks in advance!

Knex.js Incorrect integer value: '[object Object]' for column 'user_id' at row 1

I'm currently working on a project in express and I'm using knex.js to handle migrations and queries.
I'm still trying to grasp the concept of promises and how I can run multiple queries with knex.
I have the following code:
this.addUnit = function(unit_prefixV, unit_nameV, unit_descriptionV, profile_id) {
return knex.insert({ 'unit_prefix':unit_prefixV, 'unit_name':unit_nameV, 'unit_description':unit_descriptionV }).into('units')
.then(function(unit) {
return knex('users').where({ 'google_id':profile_id }).select('id')
.then(function(uid) {
return knex.insert({ 'unit_id':unit, 'user_id':uid }).into('users_units');
});
});
}
however I am returned with the following error:
Unhandled rejection Error: ER_TRUNCATED_WRONG_VALUE_FOR_FIELD: Incorrect integer value: '[object Object]' for column 'user_id' at row 1
In my routes file I have the following post method:
app.post('/dashboard/unit/add', ensureAuthenticated, function(req, res) {
let postErrors = []
if (req.body.unit_name.trim() == "") {
postErrors.push('Unit name cannot be empty.')
}
if (req.body.unit_prefix.trim() == "") {
postErrors.push('Unit prefix cannot be empty.')
}
if (req.body.unit_description.trim() == "") {
postErrors.push('Unit description cannot be empty.')
}
if (postErrors.length > 0) {
res.render('addUnit', { errors: postErrors, user: req.user })
} else {
unitModel.addUnit(req.body.unit_prefix.trim(), req.body.unit_name.trim(), req.body.unit_description.trim(), req.session.passport.user.id).then(function(unit) {
res.redirect('/dashboard')
})
}
})
For reference my users table consists of:
id
google_id
my users_units table consists of:
user_id
unit_id
What am I doing wrong?
unit is an object, you'll have to access the properties (unit_id) - depending on your db you may also have to do something special to get the result inserted object (instead of just the number of rows). The error you are getting is because knex select resolves an array. You can either do first or access the first element of the array.

Resources