I have adapted the below code from Google's Datastore tutorial. I'm vaguely aware of Promises, and I'm using await where I can figure out to do so. I've used the req object with express as below without incident, but it seems to be empty here.
It causes this error:
2021-04-16 04:55:03 default[20210415t215354] (node:10) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'name' of undefined
[SNIP]
name is a reference to a param I'm specifying like this:
curl -X POST https://MYURL/gizmos --data 'name=foo&type=bar&len=29'
What am I doing wrong? How do I avoid this?
/**
* #param {object} gizmo The gizmo record to insert.
*/
const insertGizmo = gizmo => {
return datastore.save({
key: datastore.key('gizmo'),
data: gizmo,
});
};
/**
* Retrieve the latest gizmo
*/
const getLastGizmo = () => {
const query = datastore
.createQuery('gizmo')
.order('createTime', {descending: true})
.limit(1);
return datastore.runQuery(query).then( (entities) => {
return entities[0].map(fromDatastore);
});
};
//Create a Gizmo
app.post('/gizmos', async (req, res, next) => {
const createTime = new Date();
const gizmo = {
name: req.body.name,
type: req.body.type,
length: req.body.len,
createTime: createTime,
};
try {
await insertGizmo(gizmo);
const newGizmo = await getLastGizmo();
//const [newGizmos] = await getLastGizmo();
await insertGizmo(gizmo);
const newGizmo = await getLastGizmo();
//const [newGizmos] = await getLastGizmo();
const gizmoUrl = "https://MYURL/gizmos/"+newGizmo.id;
const resText = {
"id" : newGizmo.id,
"name" : newGizmo.name,
"type" : newGizmo.type,
"length" : newGizmo.length,
"self" : gizmoUrl,
};
res.status(201).set('Content-Type', 'text/plain').send(resText).end();
} catch (error) {
next(error);
}
});
Per #hoangdv, add app.use(express.urlencoded()) somewhere. Rather node-ish not have it as the default if you ask me.
My Discord bot continuously sends [Object Promised] when I use
const DabiImages = require("dabi-images");
const DabiClient = new DabiImages.Client();
DabiClient.sfw.real.random().then(json => {
console.log(json);
}).catch(error => {
console.log(error);
});
I was wondering how I can fix this, as I'm not sure.
I think the comments on this already answer the question but you could..
const DabiImages = require('dabi-images')
const DabiClient = new DabiImages.Client()
const main = async () => {
const dabiJson = await DabiClient.sfw.real.random()
console.log(dabiJson)
}
main()
Also worth mentioning, that the sfw doesn't exist
I've been trying to deploy a Cloud Function to my Firebase project.
It's my first time doing so, also my first time programming with JavaScript.
Here's my code in Node.JS:
'use strict'
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const firebaseTriggers = functions.region('europe-west1').firestore;
const db = admin.firestore();
exports.postNotification = firebaseTriggers
.document('/post notifications/{notificatioId}').onWrite((snap, context) => {
const notifcationRecieverId = snap.data().mReciever;
const payload = {
data: {
notification_type: 'POST',
title: snap.data().mTitle,
body: snap.data().mDescription,
sender_id: snap.data().mSender,
reciever_id: snap.data().mReciever,
notification_id: context.params.notificatioId
}
};
return db.collection('dog owners')
.document(notifcationRecieverId)
.get()
.then(recieverDoc => {
console.log('Retrieving FCM tokens');
const tokens = recieverDoc.data().mTokens;
console.log('Sending notification payload');
return admin.message().sendToDevice(tokens, payload);
});
});
Upong deployment, I'm getting the following error:
Can someone help me understand why?
Firstly you have got space in your colleciton name. This is bad convetion.
post notifications => postNotifications
I have this current server code:
const express = require("express")
const fs = require("fs")
const router = express.Router()
const path = require("path")
const todos = JSON.parse(fs.readFileSync(path.join(__dirname, "../db", "todolist.json"), "utf8"))
router.get("/", async (req, res) => {
res.send(todos)
})
router.post("/new", async (req, res) => {
const { title, description } = req.body
const todoItem = {
id: "3",
title,
description
}
todos.todos.push(todoItem)
const data = JSON.stringify(todos, null, 2)
fs.writeFile(path.join(__dirname, "../db", "todolist.json"), data, () => {})
res.status(201).json(todoItem)
})
client:
console.log("Hello world!")
const somedata = {
title: "A new boy",
description: "Recieved from the client"
}
const main = async () => {
const response1 = await fetch("http://localhost:3000/todo", {
method: "GET",
})
const data1 = await response1.json()
const response2 = await fetch("http://localhost:3000/todo/new", {
method: "POST",
body: JSON.stringify(somedata),
headers: {
'Content-Type': 'application/json',
"Accept": "application/json"
}
})
const data2 = await response2.json()
return { data1, data2 }
}
main().then(data => console.log(data))
When I make a /POST request to create a new entity the browser just loops the request over and over until I manually have to quit the server. This does not happen if I use postman for some reason. Does anybody see any obvious error here with how the writeFile-method is used and why it continuously reloads the browser to keep pushing POST requests?
Thanks! :)
i had the same problem! And it took me about 1 hour to understand what my Problem is:
If you use "live server extension", the server will restart everytime, when you write, change or delete a file in the project folder!
So, if your node-app wirte a file, the live-server will restart and the app writes the file again! => loop
In my case, i write a pdf-file. All i had to do, is to tell the live server extension to ignore pdf files:
So i just add to "settings.json":
"liveServer.settings.ignoreFiles":["**/*.pdf"]
fs.writeFile is asynchronous function. So, to send a response after file written you must do it in the callback. And of course, don't forget about error checking. I.e.
router.post("/new", async (req, res) => {
const { title, description } = req.body
const todoItem = {
id: "3",
title,
description
}
todos.todos.push(todoItem)
const data = JSON.stringify(todos, null, 2)
fs.writeFile(path.join(__dirname, "../db", "todolist.json"), data, (err) => {
if(err) {
throw err;
}
res.status(201).json(todoItem)
})
})
Or you can use fs.writeFileSync as Muhammad mentioned earlier.
I think I found the problem. It seemed that the live server extension was messing things up when I had the client and server on separate ports, making the browser refresh for every request made somehow. I switched back to them sharing port, which then makes it work. I have to find a good way of separating them on a later basis without this bug happening, but that is for another time.
Thanks for your help :)
I share my working sample.body-parser dependency is need to get body in post request.Please don't change the order in server.js.Check and let me know.
and also check once whether your client code is in in loop.
My server.js
const express = require("express")
const fs = require("fs")
const router = express.Router()
const path = require("path")
const app = express();
const bodyParser = require("body-parser")
const todos = JSON.parse(fs.readFileSync(path.join(__dirname, "../db", "todolist.json"), "utf8"))
app.use(bodyParser.json());
app.use("/",router)
router.get("/todo", async (req, res) => {
res.send(todos)
})
router.post("/todo/new", async (req, res) => {
const { title, description } = req.body
const todoItem = {
id: "3",
title,
description
}
todos.todos.push(todoItem)
const data = JSON.stringify(todos, null, 2)
fs.writeFile(path.join(__dirname, "../db", "todolist.json"), data, () => {})
res.status(201).json(todoItem)
});
app.listen(3000, () => {
console.log(`Server running in Port`);
});
todolist.json
{
"todos": []
}
I think you should use fs.writeFileSync() or write some code in its callback
For clarity I have other cloud functions that all run intermittently (i.e from 'cold' in around 2-6 seconds, and all use the same boilerplate set up of importing an admin instance and exporting the function as a module)
I've seen other similar posts but this is really bugging me. I have a cloud function like so:
const admin = require('../AdminConfig');
const { reportError } = require('../ReportError');
module.exports = (event) => {
const uid = event.params.uid;
const snapshot = event.data;
if (snapshot._newData === null ) {
return null;
}
console.log('Create org begin running: ', Date.now());
const organisation = event.data.val();
const rootRef = admin.database().ref();
const ref = rootRef.child('/organisations').push();
const oid = ref.key;
const userData = {
level: 'owner',
name: organisation.name,
};
const orgShiftInfo = {
name: organisation.name,
startDay: organisation.startDay || 'Monday',
};
const updatedData = {};
updatedData[`/users/${uid}/currentOrg`] = oid;
updatedData[`/users/${uid}/organisations/${oid}`] = userData;
updatedData[`/organisations/${oid}`] = organisation;
updatedData[`/org_shift_info/${oid}`] = orgShiftInfo;
rootRef.update(updatedData, (err) => {
if (err) {
return rootRef.child(`/users/${uid}/addOrgStatus`).set({ error: true })
.then(() => {
console.log(`error adding organisation for ${uid}: `, err);
return reportError(err, { uid });
});
}
console.log('Create org wrote succesfully: ', Date.now());
return rootRef.child(`/users/${uid}/addOrgStatus`).set({ success: true });
});
}
I understand the 'cold start' thing but I think something is seriously wrong that it's taking 25 seconds. The logs don't return any error and are as so:
Is there some deeper way I can debug this to try and figure out why it's taking so long? It's unusable at the moment. Thanks a lot.
Solved:
Sorry,
I misunderstood the API a bit. I should have watched the promise video first!
I needed to put
return rootRef.update...
instead of
rootRef.update...