I am just starting node and am from PHP background. I have been trying to figure out promisses for some time now but unable to figure it out.
I am trying to use result of one query in 2nd query in a loop, but having TWO issues:
-ONE: typeof value shows an object; but when I console it out, it shows undefined
-TWO: my results are not getting in the right order. I am trying to use 'then()' but not able to quite figure it out. "inside promise 2" is consoled out before the loop in 'then()' 1 block
Here's what I'm doing in code:
exports.followers_temp = function(req, res)
{
db.sequelize.query('SELECT DISTINCT public."Users".id as user_id, public."Users".full_name, public."Users".profile_image_url, (SELECT COUNT(*) FROM public."Followships" WHERE public."Followships".leader_id = public."Users".id AND public."Followships".follower_id = :leader_id) AS is_followed FROM public."Users" INNER JOIN public."Followships" ON public."Users".id = public."Followships".follower_id WHERE public."Followships".leader_id = :leader_id LIMIT :limit OFFSET :offset', { replacements: { leader_id: req.params.leader_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT}).
then(function(data){
console.log('i am here; length: ' + data.length);
return new Promise(function(resolve, reject) {
console.log('inside promise 1, should have access to data object');
console.log('before loop');
for(let i=0; i < data.length; i++){
var temp = db.sequelize.query('(SELECT COUNT(*) AS is_following FROM public."Followships" WHERE public."Followships".leader_id = ' + data[i].user_id + ' AND public."Followships".follower_id = :my_id)', { replacements: { leader_id: req.params.leader_id, my_id: req.params.my_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT})
temp.then(function(value){
// Issue ONE
console.log('type: '+ typeof value); // it's an object
console.log('is_following: '+ value.is_following); // yet it's giving undefined
console.log('value: '+ JSON.stringify(value)); // but it prints out when I stringify it
data[i].is_followed = value.is_following;
});
}
resolve(data);
});
})
.then(function(my_array){
// Issue TWO
console.log('inside promise 2');
return res.status(200).send({
error:false,
message: my_array
});
})
.catch(function(err) {
console.log('inside promise catch');
return res.status(400).send({
error:true,
message: errorHandler.getErrorMessage(err)
});
});
};
and here is the console output:
i am here; length: 5
inside promise 1, should have
before loop
inside promise 2
type: object
is_following: undefined
value: [{"is_following":"1"}]
type: object
is_following: undefined
value: [{"is_following":"0"}]
type: object
is_following: undefined
value: [{"is_following":"1"}]
type: object
is_following: undefined
value: [{"is_following":"1"}]
type: object
is_following: undefined
value: [{"is_following":"0"}]
Please let me know -what am I doing wrong? -if you could working of promises syntax wise... would be great
Thanking you in anticipation; Please ignore rookie mistakes as I am a rookie as of now.
db.sequelize.query
is an asynchronous call put in a for
loop. This will start queries but have not successfully completed yet. So, your data
is not complete yet and you are resolving it already. With Promise.all
you can write it as follows:
Promise.all(data.map((val) => { // here val = data[i] inside the query
return new Promise((resolve, reject) => {
db.sequelize.query(...)
.then((value) => {
// modify your data object here.
resolve();
});
});
})).then(() => { resolve(data);});
You do not need to use new Promise
if you already have a promise:
exports.followers_temp = function (req, res) {
db.sequelize.query('SELECT DISTINCT public."Users".id as user_id, public."Users".full_name, public."Users".profile_image_url, (SELECT COUNT(*) FROM public."Followships" WHERE public."Followships".leader_id = public."Users".id AND public."Followships".follower_id = :leader_id) AS is_followed FROM public."Users" INNER JOIN public."Followships" ON public."Users".id = public."Followships".follower_id WHERE public."Followships".leader_id = :leader_id LIMIT :limit OFFSET :offset', { replacements: { leader_id: req.params.leader_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT })
.then(function (users) {
console.log('i am here; length: ' + users.length);
//do not use new Promise if you already have a promie
//https://stackoverflow.com/a/48576246/1641941
//use promise.all and map data to promises
return Promise.all(
users.map(
user=>{
db.sequelize.query(
'(SELECT COUNT(*) AS is_following FROM public."Followships" WHERE public."Followships".leader_id = :leader_id AND public."Followships".follower_id = :my_id)',
{ replacements:
{ leader_id: user.user_id,//changed leader_id
my_id: req.params.my_id//removed limit and offset
},
type: db.sequelize.QueryTypes.SELECT
})
.then(function (value) {
console.log('type: ' + typeof value);
//value is an array
console.log('is_following: ' + value[0].is_following);
console.log('value: ' + JSON.stringify(value));
user.is_followed = value[0].is_following;
return user;
});
}
)
)
})
.then(function (users) {
// Issue TWO
console.log('inside promise 2',users);
return res.status(200).send({
error: false,
message: users
});
})
.catch(function (err) {
console.log('inside promise catch',err);
return res.status(400).send({
error: true,
message: errorHandler.getErrorMessage(err)
});
});
};
After searching stackoverflow in more depth, I was able to solve my problem. I used help provided on THIS POST .
I thank stackoverflow community for all the help. I will try to contribute as well in future.
Final solution looks like this:
exports.followers_temp = function (req, res) {
db.sequelize.query('SELECT DISTINCT public."Users".id as user_id, public."Users".full_name, public."Users".profile_image_url, (SELECT COUNT(*) FROM public."Followships" WHERE public."Followships".leader_id = public."Users".id AND public."Followships".follower_id = :leader_id) AS is_followed FROM public."Users" INNER JOIN public."Followships" ON public."Users".id = public."Followships".follower_id WHERE public."Followships".leader_id = :leader_id LIMIT :limit OFFSET :offset', { replacements: { leader_id: req.params.leader_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT })
.then(function (users) {
var promises = users.map(function(user){
return db.sequelize.query(
'(SELECT COUNT(*) AS is_following FROM public."Followships" WHERE public."Followships".leader_id = ' +
user.user_id + ' AND public."Followships".follower_id = :my_id)',
{ replacements:
{ leader_id: req.params.leader_id,
my_id: req.params.my_id,
limit: req.params.limit,
offset: req.params.offset
},
type: db.sequelize.QueryTypes.SELECT
})
.then(function(results){
user.is_followed = results[0].is_following;
return user
})
})
Promise.all(promises).then(function(results) {
return res.status(200).send({
error: false,
message: users
});
})
.catch(function (err) {
return res.status(400).send({
error: true,
message: errorHandler.getErrorMessage(err)
});
});
})
.catch(function (err) {
return res.status(400).send({
error: true,
message: errorHandler.getErrorMessage(err)
});
});
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.