Node.js使用多个promise

时间:2017-06-13 20:48:37

标签: javascript node.js promise

我目前尝试使用两种承诺。一个用于整体召集,一个用于将用户标识用于用户名。

代码在第一次运行时有效,看起来像这样:enter image description here

上面的输出是我想要的。

但是当我再次运行查询时,我得到了这个:enter image description here

我的代码出了什么问题?我需要做些什么才能使承诺正确进行?

代码:

function getconvensations(userid) {
    return new Promise(function(resolve, reject) {

        convensations.find({members: userid}).lean().then(function (convensations) {
            var promises = convensations.map(function (currentConvensation) {
                return new Promise(function (resolve, reject) {
                    var realnames = [];
                    var usernames = currentConvensation.members.map(function (CurrentUser) {
                        Core.userDetails(CurrentUser).then(function (user) {
                            realnames.push(user.username);
                            console.log("RESOLVING USERNAMES");
                           resolve();
                        });
                    });

                    Promise.all(usernames).then(function () {
                        console.log("GET LATEST MESSAGE");
                        latestMessage(currentConvensation._id).then(function (message) {
                            console.log("Messages: ");
                            console.log(message);
                            currentConvensation.spesificmessage = message;
                            currentConvensation.users = realnames;
                            currentConvensation.otherend = (currentConvensation.members[0] == userid ? realnames[0] : realnames[1]);

                            console.log("RESOLVE LATEST MESSAGE");


                            resolve();
                        });
                    });
                });
            });

            Promise.all(promises).then(function () {
                console.log("FINISHED CONVENSATIONS");
                console.log("-------------------------");
                console.log(convensations);
                console.log("-------------------------");
                return resolve(convensations);
            }).catch(console.error);
        });
    });
}

呼叫者:

  } else if(action == 'getconvensations') {
        Messages_model.getconvensations(req.user._id).then(function (response) {
            res.json(response);
        });
    }

1 个答案:

答案 0 :(得分:2)

你的竞争条件如下:

new Promise(function (resolve, reject) {
    …
    currentConvensation.members.map(function (CurrentUser) {
        Core.userDetails(CurrentUser).then(function (user) {
            resolve();
        });
    });
    …
    latestMessage(currentConvensation._id).then(function (message) {
        resolve();
    });
    …
});

同时执行任意多个任务,履行的第一个承诺将调用resolve()

解决方案是避免Promise constructor antipattern,永远不要手动拨打new Promiseresolve!相反, chain 使用then方法保证彼此回调,并且每个函数都有return个新承诺,允许调用者等待它们。

function getconvensations(userid) {
    return convensations.find({members: userid}).lean().then(function (convensations) {
//  ^^^^^^
        var promises = convensations.map(function (currentConvensation) {
            var usernamepromises = currentConvensation.members.map(function (CurrentUser) {
                console.log("GETTING USERNAME");
                return Core.userDetails(CurrentUser).then(function (user) {
//              ^^^^^^
                    console.log("FULFILLED USERNAME");
                    return user.username;
//                  ^^^^^^
                });
            });
            return Promise.all(usernamepromises).then(function (realnames) {
//          ^^^^^^
                console.log("FULFILLED ALL USERNAMES");
                currentConvensation.users = realnames;
                currentConvensation.otherend = (currentConvensation.members[0] == userid ? realnames[0] : realnames[1]);

                console.log("GETTING LATEST MESSAGE");
                return latestMessage(currentConvensation._id);
//              ^^^^^^
            }).then(function (message) {
                console.log("FULFILLED LATEST MESSAGE");
                console.log("Message: ", message);
                currentConvensation.spesificmessage = message;
            });
        });
        return Promise.all(promises).then(function () {
//      ^^^^^^
            console.log("FINISHED ALL CONVENSATIONS");
            console.log("-------------------------");
            console.log(convensations);
            console.log("-------------------------");
            return convensations;
//          ^^^^^^
        });
    });
}