express js conditional app.get() statement - javascript

app.get('/api/notes/:id', (req, res, next) => {
fs.readFile(dataPath, 'utf-8', (err, data) => {
if (err) {
throw err;
}
const wholeData = JSON.parse(data);
const objects = wholeData.notes;
const inputId = parseInt(req.params.id);
if (inputId <= 0) {
res.status(400).json({error: 'id must be a postive integer'});
} else {
for (const key in objects) {
if (parseInt(objects[key].id) === inputId) {
res.status(200).json(objects[key])
} if (parseInt(objects[key].id) !== inputId) {
res.status(404).json({error: `bruh theres no id ${inputId}`})
}
}
}
})
})
this is my code so far i have assigned this in the global :
const dataPath = 'data.json';
and this is what the data.json file looks like
{
"nextId": 5,
"notes": {
"1": {
"id": 1,
"content": "The event loop is how a JavaScript runtime pushes asynchronous callbacks onto the stack once the stack is cleared."
},
"2": {
"id": 2,
"content": "Prototypal inheritance is how JavaScript objects delegate behavior."
},
"3": {
"id": 3,
"content": "In JavaScript, the value of `this` is determined when a function is called; not when it is defined."
},
"4": {
"id": 4,
"content": "A closure is formed when a function retains access to variables in its lexical scope."
}
}
}
if i type in the command line http -v get :3000/api/notes/3 , the error message statement executes when its suppose to execute the object with id 3
however when i delete the error message if statement. the code can retrieve object from the json file
how can i fix this?

The error you recieve
_http_outgoing.js:470 throw new ERR_HTTP_HEADERS_SENT('set'); ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
is because you use res.json() inside a for...in loop. The first iteration will break the rest because it will send a response.
The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
you should manipulate data (object/array/collection) and then send it once outside the for...in loop.
something like this:
app.get('/api/notes/:id', (req, res, next) => {
fs.readFile(dataPath, 'utf-8', (err, data) => {
if (err) {
throw err;
}
const wholeData = JSON.parse(data);
const objects = wholeData.notes;
const inputId = parseInt(req.params.id);
if (inputId <= 0) {
res.status(400).json({error: 'id must be a postive integer'});
} else {
let obj= false;
for (const key in objects) {
if (parseInt(objects[key].id) === inputId) {
obj = objects[key];
}
}
if (obj) {
res.status(200).json(obj)
} else
res.status(404).json({error: `bruh theres no id ${inputId}`})
}
}
});
});

Related

How to use sql returning id in front-end JavaScript?

I have this request in server.js file.
app.post("/insertRowtoMain", (req, res) => {
const {nodeid, maintenancetype, personnel, process, date} = req.body;
//console.log("description",description)
let insertQuery = `insert into maintenance(nodeid,maintenancetype, personnel, process, date)
values(${nodeid},'${maintenancetype}',${personnel},'${process}', '${date}') returning id`
pool.query(insertQuery, (err, result) => {
if (!err) {
console.log("insertRowtoMain", result.rows);
res.status(200).send(result.rows);
} else {
res.status(404).json(err.message)
console.log("insertRowtoMain error", err.message)
}
})
})
And I am calling this request function in front-end with this code:
const addNewMainTypes = async () => {
try {
await axios.post(`${serverBaseUrl}/insertRowtoMain`, {
nodeid: newMaintenance.nodeid,
maintenancetype: newMaintenance.maintenancetype,
personnel: newMaintenance.personnel,
process: newMaintenance.process,
date: newMaintenance.date,
});
} catch (err) {
throw err;
}
const maintenance = await getMain();
// console.log("main list", maintenanceList);
setMaintenance(maintenance);
const maintenanceList = await getMainTypes();
// console.log("main list", maintenanceList);
setMaintenanceList(maintenanceList);
};
When I insert a new row to this function, I got the returning id in server.js terminal.
How can I use that Id in front-end?
Save the response of the POST request in a variable and access the data property
// Here, "data" will be a variable with the response data
const { data } = await axios.post(`${serverBaseUrl}/insertRowtoMain`, {
nodeid: newMaintenance.nodeid,
maintenancetype: newMaintenance.maintenancetype,
personnel: newMaintenance.personnel,
process: newMaintenance.process,
date: newMaintenance.date,
});
/* Seems like your API is returning an array of objects with "id" property, so, for example... */
// The following should console.log the first element's id of the array
console.log(data[0]?.id);

Add square brackets at beginning and end of json file using Node.js

I have a JSON file and I want to add a square bracket at the beginning and end of JSON.
eg.
Input
{
"name": "Ram",
"age": 25
},
{
"name": "Laxman",
"age": 24
}
Expected output:
[
{
"name": "Ram",
"age": 25
},
{
"name": "Laxman",
"age": 24
}
]
this is a sample response, I am having a large JSON data in a file.
The best option (in my opinion) would be to open a new reader;
Open a BufferedReader
Append [
Append JSON file
Append ]
From there you can use the BufferedReader or write it into a new file.
So, we need to consider 2 situations here:
The first one is when you're responsible for creating this input file. Then, assuming you already have those objects in an array and just need to save the array itself instead of the individual objects using a for.
const fs = require('fs')
const objs = [ { "name": "Ram","age": 25},{ "name": "Laxman","age": 24} ]
const jsonData = JSON.stringify(objs)
fs.writeFile("inputFile.json", jsonData, (err) => {
if (err) {
console.log(err);
}
});
The second situation if when you don't have control to modify the input file in its creation, and are just transforming the file previously saved. In this case you'll need to completely rewrite the file due to fs limitations for positional "inserts". To do so, read the previous file into a buffer, prepend it with the opening bracket "[" and append the closing one "]" at the end. As follows:
const fs = require('fs')
const filename = 'inputFile.json'
const fileBuffer = fs.readFileSync(filename)
const newBuffer = Buffer.concat([Buffer.from('['), fileBuffer, Buffer.from(']')])
fs.writeFileSync(filename, newBuffer)
I had the same problem and after hours of searching, I found nothing so I wrote a custom code that works like a charm. Hope it helps!:)
const fs = require('fs')
var response = {};
const fsOps = async (params) => {
try {
const path = "tmp/" + params.user + ".json";
const data = params.data;
const chunksNumber = params.chunksNumber;
var chunkID = params.chunkID;
//ON FIRST CHUNK ADD [
if (chunkID === 1) {
fs.appendFile(
path, ("["), 'utf-8', function (err) {
if (err) throw err;
}
);
if (chunksNumber !== 1)
fs.appendFile(
path, JSON.stringify(data, null, 2) + ',', 'utf-8', function (err) {
if (err) throw err;
}
);
}
//WRITE CHUNKS
if (chunkID !== 1 && chunkID < chunksNumber) {
fs.appendFile(
path, JSON.stringify(data, null, 2) + ',', 'utf-8', function (err) {
if (err) throw err;
}
);
}
//ON LAST CHUNK WRITE THE LAST CHUNK AND ADD ]
if (chunkID === chunksNumber) {
console.log("LAST CHUNK")
fs.appendFile(
path, JSON.stringify(data, null, 2), 'utf-8', function (err) {
if (err) throw err;
}
);
//APPEND ] on the end of file
fs.appendFile(
path, ("]"), 'utf-8', function (err) {
if (err) throw err;
}
);
//READ THE FILE
fs.readFile(path, (err, data) => {
if (err) {
console.error(err)
return;
} else {
response = data;
}
})
//DELETE FILE
fs.unlink(path, (err) => {
if (err) {
console.error(err)
return err
}
})
}
//Return object with all the part data
return JSON.parse(response);
} catch (err) {
//IN CASE OF ERROR DELETE FILE
fs.unlink(path, (err) => {
if (err) {
console.error(err)
return err
}
})
return err;
}
}
module.exports = fsOps;

How to avoid overwrite of existing file json object in node

I am trying to solve an issue where I am trying to write a json file with user input details. But each time I input new details it is overwriting the existing data.
How can I avoid overwriting existing json object in a json file and add new object in the array instead based on user input ?
userData.json:
[
{
"name": "Name",
"number": "4334343",
"email": "email#email.com",
"message": "sdsd"
}
]
server.js :-
app.get("/myaction", function (request, response){
var name = request.query.name;
var number = request.query.number;
var email = request.query.email;
var message = request.query.message;
if (name != "") {
response.send("Your name is " + name + "number"+ number + "email"+ email + "message" + message);
const sendData = [{
name:name,
number:number,
email:email,
message:message
}];
fs.stat('./userdata.json', function(err, stat) {
if(err == null) {
console.log('File exists');
} else if(err.code === 'ENOENT') {
// file does not exist
var data = JSON.stringify(sendData,null, 2);
fs.writeFile('./userdata.json', data, (err) => {
if (!err) {
console.log('done');
}
});
} else {
console.log('Some other error: ', err.code);
}
});
} else {
response.send("Please provide info");
}
});
In order to append data instead of replacing it you can pass a+ flag to fs.writeFile:
fs.writeFile('./userdata.json', data, { flag: 'a+' }, (err) => {
if (!err) {
console.log('done');
}
});
It will create the file if the file does not exist. If the file exists, then the content will be appended.
Here is the dirty way to do it:
fs.readFile('./userdata.json', (err, data) => {
if (err){
console.log(err);
} else {
obj = JSON.parse(data);
obj.push(sendData);
json = JSON.stringify(obj);
fs.writeFile('./userdata.json', json, callback);
}});
Everytime you want to add a record, read the array, append to it and dump it again. However, consider switching to a database to avoid this.

Facebook Messenger bot problems

I made a messanager chatbot and tried to deploy it for the first time and after fighting with all kinds of errors I did connect my page, app and hooks.
Tough al seems working theres's no response from the bot. This is what i get in the error log.
I send "hi" and nothing back. When i google the response error that comes up, there's no solution that worked for me.
'use strict'
const
express=require('express'),
bodyParser = require('body-parser'),
app=express().use(bodyParser.json()); //creates http server
app.listen(process.env.PORT || 5000, () =>console.log('webhook is listening'));
app.post('/webhook', (req, res) => {
let body=req.body;
if(body.object === 'page'){
body.entry.forEach(function(entry){
//Gets the body of the webhook
let webhook_event=entry.messaging[0];
console.log(webhook_event);
//Gets the sender PSID
let sender_psid=webhook_event.sender.id;
console.log('Sender PSID: ' + sender_psid);
});
res.status(200).send('EVENT_RECEIVED');
}else{
res.sendStatus(404);
}
if(webhook_event.message){
handleMessage(sender_psid, webhook_event.message);
}else if(webhook_event.postback){
handlePostback(sender_psid, webhook_event.postback);
}
});
app.get('/', function (req, res) {
res.send('This is EngiBot Server');
});
app.get('/webhook', (req, res) => {
let VERIFY_TOKEN = "testbot_verify_token"
let mode= req.query['hub.mode'];
let token=req.query['hub.verify_token'];
let challange = req.query['hub.challange'];
if (req.query['hub.verify_token'] === VERIFY_TOKEN) {
res.send(req.query['hub.challenge']);
} else {
res.send('Invalid verify token');
}
if(mode && token){
if(mode==='subscribe' && token === VERIFY_TOKEN){
console.log('WEBHOOK_VERIFIED');
res.status(200).send(challange);
}else{
res.sendStatus(403);
}
}
});
function handleMessages(sender_psid, received_message){
let response;
if(received_message.text){
response = {
"text": 'You sent the message: "${received_message.text}". Now send an image!'
}
}else if(received_message.attachments){
let attachment_url=received_message.attachments[0].payload.url;
response = {
"attachment":{
"type": "template",
"payload":{
"template_type":"generic",
"elements": [{
"title": "Is this the right picture?",
"subtitle": "Tap a button to answer.",
"image_url": attachment_url,
"buttons": [
{
"type": "postback",
"title": "Yes!",
"payload":"yes",
},
{
"type": "postback",
"title": "No!",
"payload": "no",
}
],
}]
}
}
}
}
callSendAPI(sender.psid, response);
}
function handlePostback(sender_psid, received_postback){
let response;
let payload=received_postback.payload;
if(payload==='yes'){
response = {"text": "Thanks!"}
}else if (payload==="no"){
response ={"text": "Oops, try sending another image."}
}
callSendAPI(sender_psid, response);
}
function callSendAPI(sender_psid, response){
let request_body={
"recipient": {
"id": sender_psid
},
"message": response
}
request({
"uri":"",
"qs":{"access_token": PAGE_ACCESS_TOKEN},
"method": "POST",
"json": request_body
}, (err, res, body)=>{
if(!err){
console.log('message sent!')
}else {
console.error("Unable to send message:" + err);
}
});
}
There's a problem in the POST router. The 'webhook_event' is declared inside a foreach block inside a conditional block so its scope is internal to that block. To solve this you shall rewrite your code to match the scopes. This is the wrong router (i added some comments =
app.post('/webhook', (req, res) => {
let body=req.body;
// webhook_event == null -> true
if(body.object === 'page'){
body.entry.forEach(function(entry){
//Gets the body of the webhook
let webhook_event=entry.messaging[0]; // webhook_event declared // webhook_event == null -> false
console.log(webhook_event);
//Gets the sender PSID
let sender_psid=webhook_event.sender.id;
console.log('Sender PSID: ' + sender_psid);
});
res.status(200).send('EVENT_RECEIVED');
if(webhook_event.message){ // ReferenceError cause is not defined
handleMessage(sender_psid, webhook_event.message);
}else if(webhook_event.postback){ // ReferenceError cause is not defined
handlePostback(sender_psid, webhook_event.postback);
}
}else{
res.sendStatus(404);
}
});

Using async.js for deep populating sails.js

I have a big issue with my function in sails.js (v12). I'm trying to get all userDetail using async (v2.3) for deep populating my user info:
UserController.js:
userDetail: function (req, res) {
var currentUserID = authToken.getUserIDFromToken(req);
async.auto({
//Find the User
user: function (cb) {
User
.findOne({ id: req.params.id })
.populate('userFollowing')
.populate('userFollower')
.populate('trips', { sort: 'createdAt DESC' })
.exec(function (err, foundedUser) {
if (err) {
return res.negotiate(err);
}
if (!foundedUser) {
return res.badRequest();
}
// console.log('foundedUser :', foundedUser);
cb(null, foundedUser);
});
},
//Find me
me: function (cb) {
User
.findOne({ id: currentUserID })
.populate('myLikedTrips')
.populate('userFollowing')
.exec(function (err, user) {
var likedTripIDs = _.pluck(user.myLikedTrips, 'id');
var followingUserIDs = _.pluck(user.userFollowing, 'id');
cb(null, { likedTripIDs, followingUserIDs });
});
},
populatedTrip: ['user', function (results, cb) {
Trip.find({ id: _.pluck(results.user.trips, 'id') })
.populate('comments')
.populate('likes')
.exec(function (err, tripsResults) {
if (err) {
return res.negotiate(err);
}
if (!tripsResults) {
return res.badRequest();
}
cb(null, _.indexBy(tripsResults, 'id'));
});
}],
isLiked: ['populatedTrip', 'me', 'user', function (results, cb) {
var me = results.me;
async.map(results.user.trips, function (trip, callback) {
trip = results.populatedTrip[trip.id];
if (_.contains(me.likedTripIDs, trip.id)) {
trip.hasLiked = true;
} else {
trip.hasLiked = false;
}
callback(null, trip);
}, function (err, isLikedTrip) {
if (err) {
return res.negotiate(err);
}
cb(null, isLikedTrip);
});
}]
},
function finish(err, data) {
if (err) {
console.log('err = ', err);
return res.serverError(err);
}
var userFinal = data.user;
//userFinal.trips = data.isLiked;
userFinal.trips = "test";
return res.json(userFinal);
}
);
},
I tried almost everthing to get this fix but nothing is working...
I am able to get my array of trips(data.isLiked) but I couldn't get my userFInal trips.
I try to set string value on the userFinal.trips:
JSON response
{
"trips": [], // <-- my pb is here !!
"userFollower": [
{
"user": "5777fce1eeef472a1d69bafb",
"follower": "57e44a8997974abc646b29ca",
"id": "57efa5cf605b94666aca0f11"
}
],
"userFollowing": [
{
"user": "57e44a8997974abc646b29ca",
"follower": "5777fce1eeef472a1d69bafb",
"id": "5882099b9c0c9543706d74f6"
}
],
"email": "test2#test.com",
"userName": "dany",
"isPrivate": false,
"bio": "Hello",
"id": "5777fce1eeef472a1d69bafb"
}
Question
How should I do to get my array of trips (isLiked) paste to my user trips array?
Why my results is not what I'm expecting to have?
Thank you for your answers.
Use .toJSON() before overwriting any association in model.
Otherwise default toJSON implementation overrides any changes made to model associated data.
var userFinal = data.user.toJSON(); // Use of toJSON
userFinal.trips = data.isLiked;
return res.json(userFinal);
On another note, use JS .map or _.map in place of async.map as there is not asynchronous operation in inside function. Otherwise you may face RangeError: Maximum call stack size exceeded issue.
Also, it might be better to return any response from final callback only. (Remove res.negotiate, res.badRequest from async.auto's first argument). It allows to make response method terminal

Categories

Resources