I am not much experienced with async/await, but I have incorporated the keywords in a function which basically fetch or POST data to MongoDB database. It seems like await does not wait for the promise to be fulfilled and returns an undefined response object.
I am getting the following error:
res.error(404).json({message: e.message})
^
TypeError: Cannot read properties of undefined (reading 'error')
at Object.getAllItems (/Users/myName/Desktop/TODOList/backend/Controllers/ItemsConroller.js:12:13)
Here is my code:
ItemsController.js:
const getAllItems = async (req, res) => {
try{
const items = await Item.find({})
res.status(200).json(items)
}
catch(e){
res.error(404).json({message: e.message})
}
}
Server.js file:
app.get('/todos', (req, res) => {
dbItem.getAllItems().then(data => {
console.log("entered")
res.send(data);
})
})
Same problem with other functions in the controller file which incorporates await/async keywords.
Thanks.
You are not passing your req and res object to your /todos endpoint:
To make you app more robust try this:
You can use getAllItems as your middleware like this
app.get('/todos', dbItem.getAllItems, (req, res) => {
if(!req.error){
res.send(req.items)
}else{
res.send(req.error)
}
})
And attach your variables to the req object and pass them to /todos
const getAllItems = async (req, res, next) => {
try{
const items = await Item.find({})
req.items = items
next()
}
catch(e){
req.error = e.message
next()
}
}
Related
I wrote a small Javascript module to get rows from a MongoDB database:
async function getAll() {
await mongoose.connect(config.mongoURL).catch(err => { console.log(err); });
const conn = mongoose.connection;
conn.collection('healthdata')
.find({}).toArray().then(result => {
console.log('=>Docs:', result);
return result;
}).catch (err => {
console.log(err);
}).finally(() => {
conn.close();
});
}
exports.getAll = getAll
I get the correct display from the console ("=>Docs:").
But, when I want to get the result from the following calling function, I get the Undefined value ("Result:"):
app.get("/", async (req, res) => {
var docs = await db.getAll().then();
console.log("Result:", docs);
res.render("index.html");
});
What is missing? Wrong?
you should not mix promises with async/await, so either the answer provide by G-Force but remove the await before db.getAll() or use var docs = await db.getAll(); this should solve your problem.
Bro if you are using mongoose follow these to get data from mongoose schema
schema.find().exec().then(result=>{
console.log(result)
}).catch(error=>{
console.log(error)
})
here all schema data in result that we console if any error come it displays in console.log(error)
I think the console.log(Result:...) line is executing before your getAll completes.
I would wrap it inside the "then" clause:
app.get("/", async (req, res) => {
const docsReturned = await db.getAll()
.then(docs => {
console.log("Result:", docs);
res.render("index.html");
})
.catch(err => {
console.error(err);
}));
return(docsReturned);
I also suggest adding a catch for any errors...good practices. :)
I have a question, I don't know if I'm doing it right, I'm sure not, I want to return the answer that the GetInventory function gives me from Axios to my default route '/', someone helps me to fix and understand how do i do this?
Function:
async function getInventory() {
let res = await axios.get(getInventoryURL);
let data = res.data;
return data;
}
let inventory = getInventory();
routes.get('/', (req, res) => {
return res.json(inventory);
});
you can write your code, in this way:
Code:
const getInventory = async () => {
const response = await axios.get(getInventoryURL);
return response.data;
}
routes.get('/', async (req, res) => {
return res.json(await getInventory());
});
First of all, axios.get creates a promise. In other words, it executes asynchronous, so it's important that your code awaits the axios.get promise fulfillment before responds the request.
Att.
I have a temporary server that looks like this:
import http from 'http'
export default function tempServer(
port: number
): Promise<{ req: http.IncomingMessage; res: http.ServerResponse }> {
return new Promise((resolve) => {
const server = http
.createServer(function (req, res) {
resolve({ req, res })
// This works
// res.write('Hey!')
// res.end()
server.close()
})
.listen(port)
})
}
And I am trying to manipulate res by calling res.write in another function:
function () {
const server = tempServer(parseInt(process.env.AUTH_PORT) || 5671)
return server.then(({req, res}) => {
const data = url.parse(req.url, true).query
...
res.write('Error: ' + data.error)
res.end()
...
})
}
The result is that res.write and res.write have no effect. I am sure the issue has something to do with contexts and bindings but I am having trouble going about it. Anyone willing to indulge me?
Ok, so I know how to program in C# fairly well and I have started programming in JS recently (node js). To be honest I was in a bot of shock from async calls.
Let's say I have this code in C#:
var t_1 = SomeAsyncTask();
var t_2 = SomeOtherAsyncTask();
Task.WaitAll(t_1, t_2);
var res_1 = t_1.Result;
var res_2 = t_2.Result;
Is there a JS equivalent of this? So far I have managed this:
In User.js:
var express = require("express");
var router = express.Router();
var sqlDo = require("../../js_help/DatabasReq/sqlDo.js");
router.get("/", async function(req, res){
var json = sqlDo.ExecCommand("select * from Users");
res.send(json); //json.recordset
});
module.exports = router;
In sqlDo.js:
module.exports = {
ExecCommand: function(command){
// sql and config are defined before.
sql.connect(config, function () {
var request = new sql.Request();
request.query(command, function (err, recordset) {
if (err) console.log(err)
console.log(recordset.recordset);
return recordset;
});
});
}
};
My problem is that this code is running async. I have tried putting await to different places but nothing worked. So when I start my server it returns nothing. I can tell that it is completing a call because I let it read results into console.
Thanks for any help!
Btw: I have tried googling/stackoverlow-ing,.. But I was not able to find anything that would look like C# equivalent. Is it even possible to write it like in c#? Again thanks for every answer...
To make your ExecCommand function async, you have to make it return a Promise. Read about Promises for instance here
module.exports = {
ExecCommand: function(command){
return new Promise((resolve, reject) => { //return a Promise from the function
sql.connect(config, function () {
var request = new sql.Request();
request.query(command, function (err, recordset) {
if (err) {
reject(err); //if there is an error, reject the Promise
} else {
resolve(recordset); //if no error, resolve the Promise with the result
}
});
});
});
}
};
Depending on your SQL library, it may also support promises already, instead of callbacks
module.exports = {
ExecCommand: function(command) {
return sql.connect(config)
.then(() => {
return new sql.Request().query(command);
})
}
};
or with async/await
module.exports = {
ExecCommand: async function(command) {
await sql.connect(config);
return await new sql.Request().query(command);
}
};
Then you can call this function in the requesthandler either like this
router.get("/", async function(req, res){
try {
var json = await sqlDo.ExecCommand("select * from Users");
res.send(json);
catch (err) {
console.log(err);
res.sendStatus(500);
}
});
or like this
router.get("/", function(req, res){
sqlDo.ExecCommand("select * from Users")
.then(json => { //the promise resolved
res.send(json);
})
.catch(err => { //the promise rejected
res.sendStatus(500);
console.log(err);
});
});
I prefer the second variant. But that may be just my personal opinion ...
I have a business leve database module called "db_location" which uses the node-fetch module to get some data from a remote server via REST API.
**db_location.js** DB LOGIC
const p_conf = require('../parse_config');
const db_location = {
getLocations: function() {
fetch(`${p_conf.SERVER_URL}/parse` + '/classes/GCUR_LOCATION', { method: 'GET', headers: {
'X-Parse-Application-Id': 'APPLICATION_ID',
'X-Parse-REST-API-Key': 'restAPIKey'
}})
.then( res1 => {
//console.log("res1.json(): " + res1.json());
return res1;
})
.catch((error) => {
console.log(error);
return Promise.reject(new Error(error));
})
}
};
module.exports = db_location
I would need to call this function within a Route function so as to separate database processing from controller.
**locations.js** ROUTE
var path = require('path');
var express = require('express');
var fetch = require('node-fetch');
var router = express.Router();
const db_location = require('../db/db_location');
/* GET route root page. */
router.get('/', function(req, res, next) {
db_location.getLocations()
.then(res1 => res1.json())
.then(json => res.send(json["results"]))
.catch((err) => {
console.log(err);
return next(err);
})
});
When I ran http://localhost:3000/locations, I received the following error.
Cannot read property 'then' of undefined
TypeError: Cannot read property 'then' of undefined
It seems the Promise was empty or something wrong down the Promise chain going from one response object to another? What is a best practise for solving this kind of scenario?
EDIT 1
If I changed the getLocations to return res1.json() (which I think is a non-empty Promise according to the node-fetch documentation):
fetch(`${p_conf.SERVER_URL}/parse` + '/classes/GCUR_LOCATION', { method: 'GET', headers: {
'X-Parse-Application-Id': 'APPLICATION_ID',
'X-Parse-REST-API-Key': 'restAPIKey'
}})
.then( res1 => {
return res1.json(); // Not empty as it can be logged to `Promise Object`
})
.catch((error) => {
console.log(error);
return Promise.reject(new Error(error));
})
And the route code was changed to :
db_location.getLocations()
.then(json => res.send(json["results"]))
.catch((err) => {
console.log(err);
return next(err);
})
The exactly same error was thrown.
You need getLocations to return a Promise. At the moment, it's running a fetch, but that fetch isn't connected to anything else, and getLocations is returning undefined (and of course you can't call .then on uundefined)
Instead, change to:
const db_location = {
getLocations: function() {
return fetch( ...
Also, since you're not doing anything special in the getLocations catch block, you might consider omitting it entirely and let the caller handle it.
Your function doesn't return anything.
If you want to use a promise, you need return it.