Await doesn't seem to work, Async (nodejs) - node.js

So I'm trying to create a function which checks if the user exists in the database, if they don't it then goes and imports them to the database. I'm trying to use the await feature so it waits for the function to be completed before moving on.
const doesUserExist = (id) => {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('db');
var users = dbo.collection('user');
return new Promise(function(resolve, reject) {
users.findOne({'id': id}, function (err, user) {
if (err) throw err;
console.log('User: ', user);
if (user === null) {
resolve(false);
} else {
resolve(true);
}
});
});
});
}
const userLogin = async (user) => { // User login function
var id = String(user.id);
// Check if the user exists
var doesExist = await doesUserExist(id);
console.log(doesExist);
if(doesExist===undefined){
console.log('ERROR: Exist is empty');
return;
}
if(doesExist===false){
console.log(`User with the id ${id} does not exist.`);
addUser(user);
} else {
console.log(`User with the id ${id} does exist.`);
}
}

You aren't returning a Promise from the doesUserExist function.
You are only returning a Promise in the callback of the MongoClient connect function.
You have to refactor your code this way :
const doesUserExist = (steamid) => {
return new Promise(function(resolve, reject) {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('treehouse');
var users = dbo.collection('users');
users.findOne({'steamid': steamid}, function (err, user) {
if (err) throw err;
console.log('User: ', user);
if (user === null) {
resolve(false);
} else {
resolve(true);
}
});
});
});
}
Now, the doesUserExist function is returning a Promise that is resolved in the findOne callback.

Related

I want to return data coming from database in variable

I want to save data in accountID and using that ID want to fetch data from another collection but ID is not getting accountID
async function egetCredientials(body){
let accountID = await getAccuntID(body);
console.log(accountID);
}
async function getAccuntID(body){
return MongoClient.connect(M_URL, { useUnifiedTopology: true },async function(err, db) {
if (err) throw err;
var dbo = db.db("MES");
c_sClientID = body.sClientID;
return await dbo.collection("clients").findOne({_id:c_sClientID}, async function(err, result) {
if (err) throw err;
let allowedEmailID = result.aAllowedEmailAccounts[0];
// console.log(allowedEmailID);
return allowedEmailID;
});
});
}

how to handle async function that return promise?

I want to get a user from MongoDB. so I should use the async function to get the right result. but it return me [object , promise]. how can I use this data?
async function getUsers() {
var allUsers = null;
await MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('mydb');
dbo.collection("users").find({})
.toArray(function(err, results) {
if (err)
throw error;
db.close();
allUsers = results;
});
});
}
app.get('/user/', function(req, res) {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('mydb');
var id = req.params.id;
var allUsers = getUsers();
res.render('pages/user', {users: allUsers });
db.close();
});
});
You are mixing up promises and plain callbacks. You need to pick one or the other and consistently use it. Here's how to code it with promises - using the promises that MongoDb can return if used in the right way:
async function getUsers() {
const db = await MongoClient.connect(url);
try {
const dbo = db.db('mydb');
const results = await dbo.collection("users").find({});
return results;
} finally {
db.close();
}
}
app.get('/user/', function(req, res) {
getUsers().then(allUsers => {
res.render('pages/user', {users: allUsers });
}).catch(err => {
console.log(err);
// send some sort of error response here
res.sendStatus(500);
});
});
I removed the database operations from inside your route handler because they weren't actually doing anything and the db stuff was already inside of getUsers().

Async / Await with NodeJS + Mongoose doesn't wait

Cannot get the async / await functions to work properly in my card game app.
(a) I get the 201 response with no data.
(b) the deck document seems to be created afterwards, with the players field an empty array, indicating it is done after the deck is saved to the mongoDB
Below is my code. Any help is appreciated.
router.js
router.post('/game', (req, res, next) => {
try {
const { cards, playerNames, attributes } = req.body;
const newDeck = deck.start(cards, playerNames, attributes);
res.status(201).send(newDeck);
} catch (err) {
next(err);
};
});
/services/deck.js
exports.start = async (cards, playerNames, attributes) => {
try {
const users = await user.create(playerNames);
const deck = new Deck({
cards,
attributes,
players: users
});
return await deck.save((err, newDeck) => {
if (err) console.log(err);
console.log('RESULT', newDeck);
});
} catch (err) {
console.log(err);
}
};
/services/user.js
exports.create = async (users) => {
if (users.constructor === String) {
const user = new User({displayname: users});
return await user.save((err, newUser) => {
if (err) console.log(err);
console.log('NEW USERS ', user);
return newUser;
});
} else if (users.constructor === Array) {
let userList = [];
await users.forEach(name => {
const user = new User({displayname: name.toString()});
return user.save((err, newUser) => {
if (err) {
console.log(err);
} else {
userList.push(newUser);
return newUser;
}
});
});
console.log('NEW USERS ', userList);
return userList;
};
};
I am not familiar how you're handling promises,
but forEach is not promise-aware, that's how it has been designed, so it will not handle your asynchronous code properly
replace it with normal for loop or for-of loop, and add the await keyword in front of the user.save() method

Mongodb.connect does not execute callback function

Im trying to connect to my Mongodb and insert some documents if they are not already in the db. It works fine with the first inserts but in the function existInDatabase it sometimes does not execute the callback function.
var MongoClient = require('mongodb').MongoClient;
var mongoData = require('./mongoData');
var exports = module.exports = {};
var dbName = 'checklist';
MongoClient.connect(mongoData.ConString, {
useNewUrlParser: true
}, function(err, db) {
if (err) throw err;
for (var key in mongoData.Customers) {
if (!existsInDatabase(mongoData.Customers[key], 'Customers')) {
db.db(dbName).collection('Customers').insertOne(mongoData.Customers[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
db.close();
});
}
}
for (var key in mongoData.Categorys) {
if (!existsInDatabase(mongoData.Customers[key], 'Customers')) {
db.db(dbName).collection('Categorys').insertOne(mongoData.Categorys[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
db.close();
});
}
}
});
function existsInDatabase(obj, collection) {
var result = false;
MongoClient.connect(mongoData.ConString, {
useNewUrlParser: true
}, function(err, db) {
db.db(dbName).collection(collection).find({}).forEach(function(doc) {
if (doc.id == obj.id) {
result = true;
}
}, function(err) {
console.log(err);
});
});
return result;
}
I have made a few changes to your code. It seems you are new to async programming, spend some time to understand the flow. Feel free for any further query. Here is your code.
// Welcome to aync programming
// Here no one waits for the slow processes
var MongoClient = require('mongodb').MongoClient;
var mongoData = require('./mongoData');
var exports = module.exports = {};
var dbName = 'checklist';
// Make the connection for once only
MongoClient.connect(mongoData.ConString, { useNewUrlParser: true },
function(err, db) {
if (err) throw err;
var myDB = db.db(dbName); // create DB for once
for (var key in mongoData.Customers) {
//make call to the function and wait for the response
existsInDatabase(mongoData.Customers[key], 'Customers', function(err, result) {
//once the response came excute the next step
if (result) {
myDB.collection('Customers').insertOne(mongoData.Customers[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
});
}
});
}
for (var key in mongoData.Categorys) {
//make call to the function and wait for the response
existsInDatabase(mongoData.Customers[key], 'Customers', function(err, result) {
//once the response came excute the next step
if (result) {
myDB.collection('Categorys').insertOne(mongoData.Categorys[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
});
}
});
}
// Both the for loop will work randomly without any order
function existsInDatabase(obj, collection, cb) {
var result = false;
myDB.collection(collection).findOne({ id: obj.id }, function(err, result)
{
if (err) {
//this cb will work only when db operation is complited
cb(err);
} else if (result) {
cb(null, true);
} else {
cb(null, false);
}
});
}
});
This code may result in some error. Feel free to ask more questions over it
db.db(dbName).collection(collection).find({}) returns a cursor per the docs. You are missing .toArray():
db.db(dbName).collection(collection).find({}).toArray()...

the variable i is not filled

I have declare the variable first. but if I do console.log(userinsertData) outside looping variable still not fill.
what i should do for solving this problem?
here my code:
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
try {
data.forEach(function(item, index) {
var userdata = new User();
userdata.name = item.name;
userdata.age = item.age;
userdata.sex = item.sex;
userdata.save(function(err, data) {
if (err) {
res.send(err)
} else {
userinsertData.push(data);
}
});
})
} catch (e) {
res.json({
message: 'data not valid'
})
}
console.log(userinsertData);
res.json({
message: 'musician created!',
data: userinsertData
});
}
};
you should solve the problem as
async.eachSeries(data, function (info, callback) {
//here process your data and call callback() for next iteration
}, function (err) {
if (err) {
//this will be called after all iterations and in case of error
}else{
console.log('Well done :-!');
//this will be called after all interations successfully
}
});
this problem you are facing is because of asynchronous nature of nodejs and async helps you to introduce blocking.
Don't forget to include async
Use promise
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
new Promise(function(resolve, reject) {
data.forEach(function(item, index) {
var userData = new User(item);
userData.save(function(err, data) {
// if error, reject
if(err) return reject(err);
// we have proceed all items in data, resolve it
else if(data.length - 1 === index) return resolve(userinsertData);
// not finished yet, keep proceeding
else userinsertData.push(data);
});
}).then(function(successResult) {
res.json({
message: 'musician created!',
data: successResult
});
}, function(errorResult) {
res.json({
message: 'data not valid'
});
});
}
};
Use callbacks
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
function saveUser(callback) {
data.forEach(function(item, index) {
var userData = new User(item);
userData.save(function(err, data) {
// if error, return callback with error
if(err) return callback(err);
// we have proceed all items in data, return data
else if(data.length - 1 === index) callback(null, userinsertData);
// not finished yet, keep proceeding
else userinsertData.push(data);
});
}
saveUser(function(err, users) {
if(err) return res.json({message: 'data not valid'});
res.json({
message: 'musician created!',
data: users
});
});
}
};
This is what async package does internally

Resources