returning a boolean with asynchronous request [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I really need help with that I spent a lot of time trying to understand that but I don't get it.
I'm using nodeJS and MongoDB
I want to do a function that returns true or false depending on if the email is in the database:
I have done that
function isUserRegistered(email) {
MongoClient.connect(url, function (err, db) {
if (err) throw err;
let database = db.db(dataBaseName);
let query = { "email": email };
var userCollection = database.collection(collectionName)
userCollection.find(query).toArray(function (err, result) {
if (err) throw err;
db.close();
if (result.length > 0) {
return true;
} else {
return false;
}
});
});
}
console.log(isUserRegistered("jack#gmail.com").toString());
But when I test it doesn't work because isUserRegistered() is undefined at the time I try to print it.
I have tried to do callback functions, and I achieved to print either "false" or "true" with that, but with a callback function, I'm only starting a new function and the isUserRegister() doesn't return a boolean, so I can't do something like that later on my program:
if (isUserRegister(email){
// Try to login
} else {
// try to create the account
}
I have also look for async and await, but I don't know where I should use it.
Can it be fixed in a simple way?
Thank you

The problem is that you can't directly return a value from a callback (see this for more information).
Since the NodeJS MongoClient supports promises out of the box, you can rewrite and simplify your code with async/await very easily. Note that this still needs error handling, but it should give you a start:
async function isUserRegistered(email) {
const client = await MongoClient.connect(url);
const db = client.db(dataBaseName);
const query = {
"email": email
};
const result = await db.collection(collectionName).find(query).toArray();
if (result.length > 0) {
return true;
} else {
return false;
}
}
(async () => {
console.log(await isUserRegistered("jack#gmail.com"));
})();

Related

Variable is returning false, even though it is clearly true [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 2 years ago.
I have this snippet of code from my recent project, I am wondering why this returns false when I provide the correct input. I have put console logs everywhere and checked everything. I tried using global varibles, temp varables, all of that and nothing has worked so far.
var directoryPath = path.join(__dirname, 'images');
var result = false;
fs.readdir(directoryPath, function (err, files) {
var local = false;
//handling error
if (err) {
return console.log('Unable to scan directory: ' + err);
}
//listing all files using forEach
files.forEach(function (file) {
// Do whatever you want to do with the file
if(file == password) {
result = true;
}
});
});
return result
It may seem to you like result is true, but the single thread that runs your code sees something more along the lines of
var result = false
fs.readdir(directoryPath, function (err, files) => {...}) // thread: i'll just set this off
return result // thread: i'll return this immediately
So you're getting false when you really want true. Here's how you can do it with async/await
const main = async (directoryPath, password) => {
let result = false
let files
try {
files = await fs.promises.readdir(directoryPath)
} catch (err) {
return console.log('Unable to scan directory: ' + err);
}
files.forEach(file => {
if (file == password) {
result = true
}
})
return result // now result will be true if file == password
}

ExpressJS function can't return

I've been trying to develop an app working on Electron with an Express webserver. I also use mysql npm package for database stuff. But there's something wrong with the login function and I wasn't able to find the problem. I hope you could help.
server.js
function userLogin(data){
con.query(`SELECT * FROM players WHERE player_username = '${data.login_username}'`, (err, result, fields) => {
if (err) throw err;
var compare = bcrypt.compareSync(data.login_password, result[0].player_password);
if(compare == true) {
return "1";
}
else{
return "0";
};
});
};
app.route('/login').post((req,res) => {
res
.json(userLogin(req.body))
.end();
});
Everything is defined. No errors are shown but the function can't return, I don't understand why. If I add a console.log above return, it logs the result so the query is also OK, but the function doesn't return anything, literally anything.
Since userLogin is an asynchronous function, you can't just call it like a normal function and expect it to return a value. Instead, you should work on its results from inside the callback of con.query when they are available, like so:
app.route('/login').post((req, res) => {
con.query(`SELECT * FROM players WHERE player_username = '${data.login_username}'`, (err, result, fields) => {
var compare = bcrypt.compareSync(data.login_password, result[0].player_password);
res.json(compare ? "1" : "0").end();
});
});
You have to wait for the query to complete before sending the response. One way is to convert it into Promise and another is to use a callback
function userLogin(data, onComplete){
con.query(`SELECT * FROM players WHERE player_username = '${data.login_username}'`, (err, result, fields) => {
if (err) throw err;
var compare = bcrypt.compareSync(data.login_password, result[0].player_password);
if(compare == true) {
onComplete("1"); // do callback function
}
else{
onComplete("0");
};
});
};
app.route('/login').post((req,res) => {
userLogin(req.body, (val) => {res.json(val).end(); } ) // pass the function as callback
});

How to store the result object of a query into an object variable in nodejs [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 4 years ago.
I am using this query to select all records from the products table and I want to store them inside an object variable which later I can use it for other purposes, so I tried this
var SelectQuery = "Select * FROM `products`";
var ProductDetails = {};
conn.query(SelectQuery, function (err, result) {
if(err) {
console.log(err);
} else {
ProductDetails = result;
}
});
console.log(ProductDetails);
But in Console I get this {}.
(Thanks to user jfriend00 for pointing out a major oversight in my original answer)
If conn.query is returning a promise then you could make this work in the manner you are describing by using async/await:
async function getProducts() {
var SelectQuery = "Select * FROM `products`";
var ProductDetails = {};
await conn.query(SelectQuery, function(err, result) {
if (err) {
console.log(err);
} else {
ProductDetails = result;
}
});
console.log(ProductDetails);
}
But note this only works if your conn.query returns a promise. Also, it is a newer ES feature, so you may need to transpile it depending on your node version. Also, note that the function this takes place in will need to be wrapped with async.
Otherwise, the other candidates to leverage for handling asynchronicity are callback functions and Promises.
If conn.query does not return a promise, you could write your own query implementation that would return a promise so you could leverage async/await:
function asyncQuery(sqlQuery) {
return new Promise((resolve, reject) => {
conn.query(SelectQuery, function(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
})
})
}
Then the original function could be rewritten as:
async function getProducts() {
var SelectQuery = "Select * FROM `products`";
var ProductDetails = await asyncQuery(SelectQuery);
console.log(ProductDetails);
}

getting async nodejs value from each callback calls [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
var async = require('async');
var square = function (id, callback) {
Business.prototype.getBusinessUser(id,function(userObject){
return callback(userObject);
});
};
async.eachSeries(findBusinessResult, function (businessObject, callback) {
//console.log("results from square");
var result = square(businessObject["id"] , function(result){
console.log(result);
});
callback(); // Alternatively: callback(new Error());
}, function (err,results) {
if (err) { throw err; }
console.log('Well done :-)!');
console.log(results);
});
Why does the result always become undefined: any help please.
async is reserved word in ES7 and might give you problem later, when it's implemented.
What you might want to consider is actually using async/await togheter with babel.
Some browser is starting to implement it already
var square = id =>
new Promise(rs =>
Business.prototype.getBusinessUser(id, rs)
)
async search() {
for (let businessObject of findBusinessResult) {
let result = await square(businessObject.id)
console.log(result)
}
}
I hope this will be a game changer solution for most ppl. This is making ASYC java callback into somthing which look like sync with effiecent callback handling. Its my three days of challange. [Callbacks][1] are indeed a a major challage in javacript and here is how to solve issue using promises .
install bluebird
npm install bluebird --save
//inyour code
var Promise = require('bluebird'); //yeah awsome bird indeed :)
function extendBusinessObjectPromise(id,element) {
return new Promise(function(resolve, reject) {
Business.prototype.getBusinessUser( id ,function(userObject){
var extend = require('util')._extend;
mergedJson = userObject;
elements = element;
extend({},elements);
extend(elements,mergedJson);
global.businesssWithUsers.push(elements); //sahred object
resolve(global.businesssWithUsers)
})
})
}
//NOW how do you i call the promise result inside a foreach loop and get its value returned as callback result. seem crazy idea :(
Person.prototype.getPersons = function(filter , callback) {
//this my own Bill count since i have one using one user account
global.businesssWithUsers = [];
models.PersonModel.findAll(filter_combined).then(function (findBusinessResult) {
global.businesssWithUsers = []
var extend = require('util')._extend;
var mergedJsonArray = [];
if (findBusinessResult==null) {
return callback(false,"no result found");
}
var promiseBusinessResult = null; //promise reslover :)
var findBusinessResult =JSON.parse(JSON.stringify(findBusinessResult));
findBusinessResult.forEach(function(eachElement) {
var id = element["userId"];
promiseBusinessResult = extendBusinessObjectPromise(id,element);
});
promiseBusinessResult.done(function(result){
callback(true,result); //pass the result to main function
});
}).catch(function (err) {
log.error(err["errors"][0]["message"])
callback(false,err["errors"][0]["message"])
return
})
}
Success at last. Cheers!

Node.JS callback inside while [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
What I want to do:
var found = false;
while (!found){
var result = db.getNextRecord();
if (result == search_term){
return result;
}
}
The problem is, getNextRecord is asynchronous
var nothing_returned = db.getNextRecord(function(err, result){
// I have the result in this callback, but not before
});
Given the behavior of getNextRecord(cb), how can I rewrite the above code snippet to get the same outcome?
Since you have a function that's async and you want to call in synchronously, you have two choice. Use a sync version of the method if there is one available, but if not, then you'll have to change your logic.
The following snippet should do what you want, it does require the async library.
var async = require('async');
var result;
async.whilst(
function () {
return !result;
},
function (callback) {
db.getNextRecord(function (err, record) {
if (err)
{
return callback(err);
}
if (result == search_term)
{
result = record;
}
return callback();
});
},
function (err) {
// Search is complete, do what you wish with result in this function. This function
// will be called when whilst is done or if getNextRecord got an error.
}
);
I'm sure there's a shorter way to do this if you want to change the logic even more, but this is similar to doing a while but asynchronously.
Use the async library. Its until function looks like what you need: https://www.npmjs.com/package/async#until
var async = require('async');
var latestResult = null;
async.until(function () {
return latestResult == search_term;
}, function () {
db.getNextRecord(function (err, result) {
latestResult = result;
});
}, function () {
// now you can do something with latestResult
});
You should also consider whether it makes sense to do this in your app or have the database query include this filtering.
With babel and new JS:
import {promisify as pr} from 'es6-promisify';
async function find(search_term) {
let found = false, result=null;
while (!found){
let result = await pr(db.getNextRecord)();
if (result == search_term){
found=true;
}
}
return result;
}

Categories

Resources