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!
Related
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"));
})();
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);
}
This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Closed 6 years ago.
I have this node js app working with several callback functions which I am trying to promisify to no avail.
Its getting to the point where I dont know if it is even possible. If you can help me promisify the code below I'll probably be able to do the rest of it:
var i2c_htu21d = require('htu21d-i2c');
var htu21df = new i2c_htu21d();
htu21df.readTemperature(function (temp) {
console.log('Temperature, C:', temp);
});
Any insight helps!!!
The common pattern is:
<promisified> = function() {
return new Promise(function(resolve, reject) {
<callbackFunction>(function (err, result) {
if (err)
reject(err);
else
resolve(result);
});
});
}
For your specific example (to which you might want to add error handling):
readTemperature = function() {
return new Promise(function(resolve) {
htu21df.readTemperature(function (temp) {
resolve(temp);
});
});
}
readTemperature().then(function(temp) {
console.log('Temperature, C:', temp);
});
You need to use bluebird for this.
var bluebird = require('bluebird');
var i2c_htu21d = require('htu21d-i2c');
var htu21df = new i2c_htu21d();
var readTemperature = bluebird.promisify(htu21df.readTemperature);
readTemperature().then((temp) => {console.log('Temperature, C:', temp);});
I am trying to perform sql queries based on the callback results in if conditions but i am unable to write the code .so please provide som information in code
app.get('/resell-property', function(req, res) {
var data = {}
data.unit_price_id = 1;
function callback(error, result) {
if (result.count == 0) {
return hp_property_sell_request.create(data)
}
else if (result.count > 0) {
return hp_unit_price.findAll({
where: {
unit_price_id: data.unit_price_id,
hp_property_id: data.property_id,
hp_unit_details_id: data.unit_details_id
}
})
}
}
hp_property_sell_request.findAndCountAll({
where: {
unit_price_id: data.unit_price_id
}
}).then(function (result) {
if (result) {
callback(null, result);
}
});
});
In this how can i write the callbacks for
hp_property_sell_request.create(data) ,hp_unit_price.findAll({
where: {
unit_price_id: data.unit_price_id,
hp_property_id: data.property_id,
hp_unit_details_id: data.unit_details_id
}
})
In that after returning result again i have to handle callbacks and perform this query
if(result.request_id){
return hp_unit_price.findAll({
where:{
unit_price_id:result.unit_price_id,
hp_property_id:result.property_id,
hp_unit_details_id:result.unit_details_id
}
}).then(function (result){
if(result.is_resale_unit==0 && result.sold_out==0){
return Sequelize.query('UPDATE hp_unit_price SET resale_unit_status=1 WHERE hp_unit_details_id='+result.unit_details_id+' and hp_property_id='+result.property_id)
}
})
}
The promise resolve function takes only one input argument, so if you need to pass in multiple stuff, you have to enclose them in a single object. Like, if you have to go with something like:
database.openCollection()
.then(function(collection){
var result = collection.query(something);
var resultObject = { result: result, collection: collection };
})
.then(function(resultObject){
doSomethingSyncronousWithResult(resultObject.result);
resultObject.collection.close();
});
You can't use Promise all if all of your stuff isn't a result of a promise resolve, you might need to go with something like this.
Disclaimer: The code example is a very poor one, but it explains the concept.
I would suggest you to learn about Promises, particularly Bluebird.
You can promisify traditional callback methods.
I would also create model level functions in different files. Here's an example.
parent.js
const db = require("./connections/database"); // connection to database
const getChildForParent = function (parentId, childId, callback) {
db.find({parent: parentId, child_id: childId}, "childrenTable", function(err, result) {
if (err) {
return callback(err);
}
return callback(null, result);
});
};
children.js
const db = require("./connections/database"); // connection to database
const getToysForChild = function (childId, callback) {
db.find({toy_belongs_to: parentId}, "toysTable", function(err, result) {
if (err) {
return callback(err);
}
return callback(null, result);
});
};
Then in controller you can do something like this:
const Bluebird = require("bluebird");
const Parent = require("./parent.js");
const Child = require("./child.js");
// Promisifying adds "Async" at the end of your methods' names (these are promisified)
Bluebird.promisifyAll(Parent);
Bluebird.promisifyAll(Child);
// Just an example.
app.get("/parent/:parentId/children/:childId", function(req, res) {
return Bluebird.try(function() {
return User.getChildForParentAsync(req.params.parentId, req.params.childId);
}).then(function(child) {
return Child.getToysForChildAsync(child.child_id);
}).then(function(toys) {
// Do something with toys.
});
});
Of course you can do much more with this and this is not the only way.
Also you can use Promise.all(). This method is useful for when you want to wait for more than one promise to complete.
Let's say you have a list of urls that you want to fetch and process the results after all the data has been fetched.
var urls = [url1, url2, url3, url4, url5 .......... ];
var Bluebird = require("bluebird");
var request = require("request"); // callback version library
Bluebird.promisifyAll(request);
// create a list which will keep all the promises
var promises = [];
urls.forEach(function(url) {
promises.push(request.getAsync(url1));
});
// promises array has all the promises
// Then define what you want to do on completion.
Bluebird.all(promises).then(function(results) {
// results is an array with result a url in an index
// process results.
});
I would recommend to use Promises to solve that. If you need all results of all Requests, when they are all done Promise.all() will do that for you. Your basic could look like that:
var req1 = new Promise(function(res, rej){
var req = new XMLHttpRequest()
…
req.addEventListener('load', function (e) {
res(e);
})
var req2 = //similar to the above
Promise.all([req1, req2, …]).then(function(values){
//all requests are done here and you can do your stuff
});
You can also use the new fetch api, which creates Promises like so:
var req1 = fetch(…);
var req2 = fetch(…);
Promise.all([req1, re2, …]).then(…);
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;
}