I currently have a problem with my function. I'm using a MongoDB Database to check is something exists and as you can see, if a data value is true, I wanna set the return value of the function to false or when it's wrong it should return false.
Everything works to this point.
The function is just returning "undefined". I tried everything I could think of and tested atleast one hour but couldn't find any solution.
I hope anyone of you guys could help me to return a true or false here.
Thanks for your help :D
Note: Also tried it with async before, didn't work out
function CheckActiveGamesPlayer1(memberid) {
console.log("3")
db.findOne({ GuildID: guild.id, Player1: memberid }, async(err, data) => {
if (data.Ingame === true) {
console.log("4")
Embed.setDescription(`<#${memberid}> is in an active game. Can't start the game!`).setColor("RANDOM");
channel.send({ embeds: [Embed], ephemeral: true })
return false;
} else {
console.log("5")
return true;
}
})
}
That is because you aren't actually returning anything in CheckActiveGamesPlayer1. However, you are returning something in your db.findOne callback.
I am not sure how you are calling the CheckActiveGamesPlayer1 function, but I would suggest returning a Promise so you can either await or .then it to get the response you're after.
function CheckActiveGamesPlayer1(memberid) {
console.log('3');
return new Promise( (resolve, reject) => {
db.findOne({ GuildID: guild.id, Player1: memberid }, async (err, data) => {
if (data.Ingame === true) {
console.log('4');
Embed.setDescription(`<#${memberid}> is in an active game. Can't start the game!`).setColor('RANDOM');
channel.send({ embeds: [Embed], ephemeral: true });
resolve(false);
} else {
console.log('5');
resolve(true);
}
});
});
}
You can then call your function and get the response by .then
IE:
CheckActiveGamesPlayers1(1).then( result => console.log(result) );
You can also add async to your CheckActivePlayers1 function so you can just await it.
IE:
async function CheckActiveGamesPlayer1(memberid) { ... }
const result = await CheckActiveGamesPlayers1(1);
I am not sure which version of mongo you are working with. But there's a chance you can just return db.findOne as long as that returns a promise. The way you are currently using db.findOne is in the form of a callback, so there would be some code re-arranging if you went this route.
https://www.mongodb.com/docs/drivers/node/current/usage-examples/findOne/
Try something like this. db.findOne probably returns a promise, so you can do await db.findOne instead of providing a callback, then you can return like normal after that.
async function CheckActiveGamesPlayer1(memberid) {
console.log("3")
const data = await db.findOne({ GuildID: guild.id, Player1: memberid });
if (data.Ingame === true) {
console.log("4")
Embed.setDescription(`<#${memberid}> is in an active game. Can't start the game!`).setColor("RANDOM");
channel.send({ embeds: [Embed], ephemeral: true })
return false;
} else {
console.log("5")
return true;
}
}
This is not an async function. Your function runs first, returns with undefined.
Then, the async callback is called but that value is passed to nothing.
One way to fix this is to make this an async function, then use "await" keyword.
Related
I am trying to check weather an account associated with the same username already exists or not. I am using the exist method to check but I keep getting a large object instead of a Boolean value.
async checkExisting(username,userCollection) { //WORK ON ISSUE WITH VERIFYING
const check = new Promise((resolve,reject) => {
let value = userCollection.exists({username})
console.log(value);
// if(userCollection.exists({username})) {
// reject("Username taken")
// }
resolve("Username avaliable")
})
return check;
},
Your code is correct. It's just what you write in resolve is returned.
And no need to make the function async as you're already returning a Promise. So where you call this function there just keep await as follows
await checkExisting('username', 'collection')
checkExisting(username, userCollection)
{
return new Promise((resolve, reject) => {
userCollection
.exists({username})
.then((value) => {
if (value) {
resolve(true)
}
resolve(false)
})
.catch((err) => reject(err))
})
}
Note: You can use either promise or async-await syntax; both ways are correct. However, never combine these two concepts as it will give unexpected output.
userCollection.exists({username}) returns a query that you never ran. You need to actually execute it and wait for the result. Also avoid the Promise constructor antipattern. Just do
async checkExisting(username,userCollection) {
const check = await userCollection.exists({username})
if (check) {
throw new Error("Username taken");
}
return "Username avaliable";
},
I'm making a module for my database, but I dont know why my function is returning a Promise, heres the code:
async function GetGuildData(guildID) {
if(await guildDataModel.exists({ guildID: guildID })) {
guildDataModel.findOne({ guildID: guildID }).then(document => {
return document;
}).catch(error => console.error("[ERROR] An error ocurred while I was trying to get guild data:\n\n".red, error));
} else {
return console.error("[ERROR] The guild doesn't exist".red)
};
};
Please help, I dont know why is this ocurring:
MongoDB - Mongoose
Like everyone has said async functions always return promises,
also this would not work:
.then(document => {
return document;
});
It does essentially nothing. You would need to return the promise in the if statement, as so:
if(await guildDataModel.exists({ guildID: guildID })) {
return guildDataModel.findOne({ guildID: guildID });
}
and then in some other section
const data = await GetGuildData(guildID).catch(err => {});
This is one of the implicit gotchas ES6 has brought.. Check out MDN docs:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Async functions return a Promise
If what you return is not already a promise, it wrapped with a Promise:
Promise.resolve(whatever)
If you don't want to use then, you might do something like:
!async function(){
//define GetGuildData
let data = await GetGuildData(whatever);
//do something with data
}();
I'm making a function to return a boolean to know if an element is present or not, but I get
this is the status: false
How can I get an only true or false response, please help, I'm using an if condition but it shows that response...
async IsPresent(element){
try{
await element.isPresent().then(function(status){
console.log("this is the status: " + status);
return status;
});
}
catch(err){
return console.log(err);
}
};
this is the function where I'm calling IsPresent
async ClickSomething(){
try{
await this.helpers.ClickElement(oneElement);
if(await this.helpers.IsPresent(anotherElement) == false){
//Do something
}else{
//Do something esle
}
catch(err){
return console.log(err);
}
};
There is a lot of unnecessary code in that function. You could achieve the same functionality using the following
async IsPresent(element){
try {
return await element.isPresent();
}
catch (err) {
return console.log(err);
}
};
First thing to note is that when a function is declared async you are able to use the await keyword to pause the execution until that any associated promise is resolved. You are actually using two different approached to resolve promises here (promise.resolve and .then()) when only awaits are necessary.
Second thing to note is that isPresent return true or false anyway so that can be directly returned from your function.
This is my code snippet:
await firestore.runTransaction(t => {
t.get(docRef)
.then(docRef => {
logger.info("entering transaction");
if (!docRef.exists) {
t.create(docRef, new Data);
return Promise.resolve();
} else {
t.update(docRef, {aField: updateData});
return Promise.resolve();
}
})
.catch(error => {
return Promise.reject(error);
});
})
This gives me the following error:
Error: You must return a Promise in your transaction()-callback. at transaction.begin.then (/srv/node_modules/#google-cloud/firestore/build/src/index.js:496:32) at
It's my first time using firestore transaction syntax, and I know fairly about nodejs promise concepts and syntax. I mimiced the firestore transaction example here and wrote the above snippet.
After the error, I tried to change Promise.resolve() to Promise.resolve(0), but in vain.
I also tried to remove await and instead use .then, but it still gives me the same error.
Please shed some lights on it. Appreciate it. Thanks.
You need to basically return the Promise. Also, if t.create and t.update returns a promise as well, you can just return that. Don't do return Promise.resolve(), Which is wrong because it will resolve BEFORE actually inserting or creating.
Assuming everything works fine you need to do:
await firestore.runTransaction(t => {
return t.get(docRef)
.then(docRef => {
logger.info("entering transaction");
if (!docRef.exists) {
return t.create(docRef, new Data);
} else {
return t.update(docRef, { aField: updateData });
}
})
.catch(error => {
return Promise.reject(error);
});
})
Looking back the example, I realized i missed return in return t.get() but the error was in no way obvious to point out my mistake..
Take the following contrived example:
const housekeepingStuff = async function (data) {
const result = await notImportant(data);
result.more = 'yawn';
storeInDatabase(result);
};
const getStuff = async function () {
try {
const data = await getData();
data.extra = 'wow';
housekeepingStuff(data); // <---- don't want to await... but need to for error catching
return Promise.resolve(data);
} catch (err) {
return Promise.reject(err);
}
};
try {
const myData = await doSomeStuff();
res.send(myData);
} catch (err) {
console.log(err);
res.sendStatus(400);
}
I want to return the data from getStuff () ASAP without waiting for housekeepingStuff() but if I don't await that function then I have an uncaught error.
I could call housekeepingStuff() outside the getStuff() function, after getting and sending the data to whoever wants it:
try {
const myData = await doSomeStuff();
res.send(myData);
await housekeepingStuff(data); // <---- am awaiting but who cares because nothing follows
} catch (err) {
console.log(err);
res.sendStatus(400);
}
But that doesn't seem right because I don't want to have to remember to call housekeepingStuff() every time I call doSomeStuff()... it should ideally be handled "internally".
What is the correct approach here?
A promise (or async) function has 2 possible outcomes:
A successful outcome
An error outcome
To get either outcome, you must wait for it. You can't wait for 1 condition and not for the other, because the entire thing needs to execute so you can find out what the outcome was.
Otherwise you're really asking the javascript engine: Please predict for me if the function will fail, and if it does, await it.
The correct approach therefore is to just await it.
However, if you don't care about either successful or failed outcomes of this function, just call the function via another async function that eats all the errors:
async function doSomeStuffAndIgnoreError() {
try {
await doSomeStuff();
} catch (e) {
console.error(e);
}
}