Reputation: 1364
I have this really weird issue where my Promise's .then is not working. The error is below:
TypeError: Cannot read property 'then' of undefined
The reason I call this weird is because I am using the same structure everywhere else and it works flawlessly. I would also like to add that the actual action it is supposed to do - does get done! So this is purely an issue with the way my Promises are "coded" - just syntactic sugar.
My code snippet is as below:
var updateAllUnreadNotifications = function(){
userModel.aggregate([
{$match:{"profileID": 123}},
{$unwind: "$notifications"},
{$match:{"notifications.read": false}},
{$group: {_id:"$_id", notifications: {$push:"$notifications"}}}
], function(err, notifications){
var notificationPromises = notifications.map(function(notification) {
return new Promise(function(resolve){
userModel.findOneAndUpdate(
{profileID: 123, "notifications.id": notification.id},
{"notifications.$.read": true},
{safe: true},
function(err, result) {
if (err){
return;
} else if (result){
resolve(notification);
}
}
);
});
});
return Promise.all(notificationPromises);
});
};
updateAllUnreadNotifications()
.then(function(notifications){
res.json({
message: 'All is well'
});
});
Furthermore, I have done a console.log on the notificationPromises and it does look like a chain of Promises. And of course, the result variable is also there so this is not an issue with the DB command.
What have I messed up? I am sure it will be a very obvious one but for the life of me, I can't isolate it.
Let me know if some more information is required.
Upvotes: 0
Views: 237
Reputation: 665364
You return
from the userModel.aggregate
callback - which cannot work - instead of from the updateAllUnreadNotifications
function. It does return undefined
, on which you try to invoke the then
method. You will need to promisify that as well:
function aggregateAsync(x) {
return new Promise((resolve, reject) => {
userModel.aggregate(x, (err, res) => {
if (err) reject(err);
else resolve(res);
});
});
}
function findOneAndUpdateAsync(x, y, z) {
return new Promise((resolve, reject) => {
userModel.findOneAndUpdate(x, y, z, (err, res) => {
if (err) reject(err);
else resolve(res);
});
});
}
With those, you can do
function updateAllUnreadNotifications() {
return aggregateAsync([
{$match:{"profileID": 123}},
{$unwind: "$notifications"},
{$match:{"notifications.read": false}},
{$group: {_id:"$_id", notifications: {$push:"$notifications"}}}
]).then(notifications => {
var notificationPromises = notifications.map(notification => {
return findOneAndUpdateAsync(
{profileID: 123, "notifications.id": notification.id},
{"notifications.$.read": true},
{safe: true}
);
});
return Promise.all(notificationPromises);
});
}
updateAllUnreadNotifications().then(notifications => {
res.json({
message: 'All is well'
});
});
Upvotes: 1
Reputation: 16482
You need to return promise
from updateAllUnreadNotifications
function but you are not returning anything from that function. That's why you are getting that error.
I would say a better way is that make a separate function for processing notification and chain the promises like this
var updateAllUnreadNotifications = function(){
return new Promise(function(resolve,reject){
userModel.aggregate([
{$match:{"profileID": 123}},
{$unwind: "$notifications"},
{$match:{"notifications.read": false}},
{$group: {_id:"$_id", notifications: {$push:"$notifications"}}}
], function(err, notifications){
if(err){ reject(err)}
// If got notifications then resolve
// notifications will be available to next then function
resolve(notifications)
})
})
}
var processNotifications = function(notifications) {
var notificationPromises = notifications.map(function(notification) {
return new Promise(function(resolve){
userModel.findOneAndUpdate(
{profileID: 123, "notifications.id": notification.id},
{"notifications.$.read": true},
{safe: true},
function(err, result) {
if (err){
return;
} else if (result){
resolve(notification);
}
}
);
});
});
return Promise.all(notificationPromises);
};
// Chain one extra then here to process notifications
updateAllUnreadNotifications().then(processNotifications)
.then(function(notifications){
res.json({
message: 'All is well'
});
});
Upvotes: 1