Javascript 节点中的承诺不起作用-。则未定义

Javascript 节点中的承诺不起作用-。则未定义,javascript,node.js,promise,Javascript,Node.js,Promise,我有一个很奇怪的问题,我的承诺是,然后就不起作用了。错误如下: TypeError:无法读取未定义的属性“then” 我之所以称之为怪异,是因为我在其他任何地方都使用相同的结构,而且工作完美无瑕。我还要补充一点,它应该采取的实际行动——确实做到了!所以这纯粹是我的承诺“编码”方式的问题——只是语法上的糖分 我的代码片段如下所示: var updateAllUnreadNotifications = function(){ userModel.aggregate([ {$m

我有一个很奇怪的问题,我的承诺是,然后就不起作用了。错误如下:

TypeError:无法读取未定义的属性“then”

我之所以称之为怪异,是因为我在其他任何地方都使用相同的结构,而且工作完美无瑕。我还要补充一点,它应该采取的实际行动——确实做到了!所以这纯粹是我的承诺“编码”方式的问题——只是语法上的糖分

我的代码片段如下所示:

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'
    });
});
此外,我在NotificationPromissions上做了一个控制台.log,它看起来确实像一个承诺链。当然,result变量也存在,因此这不是DB命令的问题

我搞砸了什么?我相信这将是一个非常明显的问题,但就我个人而言,我不能孤立它


如果需要更多信息,请告诉我。

您需要从
updatealunreadnotifications
函数返回
promise
,但您没有从该函数返回任何内容。这就是为什么你会犯这样的错误

我想说一个更好的方法是为处理通知创建一个单独的函数,并像这样链接承诺

    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'
        });
    });

您需要从
updatealunreadnotifications
函数返回
promise
,但您不会从该函数返回任何内容。这就是为什么你会犯这样的错误

我想说一个更好的方法是为处理通知创建一个单独的函数,并像这样链接承诺

    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'
        });
    });

userModel.aggregate
callback返回
,而不是从
updatealunreadnotifications
函数返回。它确实返回
undefined
,您尝试在其上调用
then
方法。您还需要:

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);
        });
    });
}
有了这些,你就能做到

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'
    });
});

userModel.aggregate
callback返回
,而不是从
updatealunreadnotifications
函数返回。它确实返回
undefined
,您尝试在其上调用
then
方法。您还需要:

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);
        });
    });
}
有了这些,你就能做到

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'
    });
});

您没有从
updatealUnreadNotifications
返回任何内容。添加一个
returnusermodel.aggregate([…])userModel.aggregate([
看起来您有一些语法错误,这就是您正在使用的代码吗?我遗漏了“函数”我的userModel.aggregate行。现在,它已完成。我很抱歉。您没有从
updatealunreadnotifications
返回任何内容。添加
return userModel.aggregate([…]);
Hey mate,谢谢您指出。我认为我的“返回新承诺”行将覆盖它,但想起来,这是针对.map循环的。您介意引导我到正确的方向吗?不用说,有点JS新手。@ShayanKhan编辑您的问题。我没有看到
userModel.aggregate的相应结束
]
括号([
看起来您有一些语法错误,这就是您正在使用的代码吗?我漏掉了“函数”我的userModel.aggregate行。现在,它完成了。我的道歉。很好。让我马上开始,然后像魅力伴侣一样回到你身边。非常感谢!很好。让我马上开始,然后像魅力伴侣一样回到你身边。非常感谢!谢谢你的回答。我也会尝试这个(如你所见,另一个答案对我有效)。但作为一项学习练习,我将仔细阅读你的代码,以便我能更多地理解承诺。每次我认为我已经实现了承诺,我都会迷路。谢谢你的答案Bergi。我也会尝试这个(如你所见,另一个答案对我有效).但作为一个学习练习,我会仔细阅读你的代码,这样我就可以更多地理解承诺。每次我认为我已经兑现了承诺,我都会迷失方向。