0

浏览了 bluebird 自述文件示例,我仍然想知道如何实现/转换一些异步代码以涉及带有 .then 的承诺。

这里有许多 ifStatements,但主要的一点是,当循环遍历时toArray,如果element数据库中存在 (findOne),然后将其分配给一个变量,以 .push 到 new ( .post & .save) 数据库文档。

这是当前的异步代码,因此在 .save 之后运行 findOne .. 但它需要在之前运行:

// create a story (accessed at POST http://localhost:4200/api/v1/story)
.post(function(req, res) {

    console.log('posting a new Story..from: ' + res.locals._id + '..' + res.locals.username );

    var story = new Models.Story();

    var toArray = req.body.to;
    console.log(toArray); // [ 'user1', 'user2', 'user3' ]
    toArray.forEach(toArrayLoop);
    function toArrayLoop(element, index, array){

        console.log('element: ' + element); // 'user1' .. 'user2' .. 'user3'

        var out = false; // if sent to Self, out = true
        if (element == res.locals.username) {out = true; console.log('to element: ' + element + ' == res.locals.username: ' + res.locals.username)}

        var toUserId = '';
        if (element) {
            Models.User.findOne({username: element}, function (err, user) {

                if (user) {

                if (err) {
                    console.log(err);
                    res.send(err);
                }
                    console.log('user._id = ' + user._id);
                    toUserId = user._id;
                } else {
                    toUserId = '';
                    console.log('toUserId = ' + toUserId);
                }

            });
        }

        story.to.push({

            user : toUserId, // push the findOne user._id
            username : element, // push the toArray element
            view :
            {
              inbox: true,
              outbox: out,
              archive: false,
            },
            updated : req.body.nowDatetime

        });

    }

    var archive = false;
    console.log('req.body.archive = ' + req.body.archive);
    if (req.body.archive == 'true') { archive = true; console.log('archive = ' + archive); };

    var in = false;
    toArray.forEach(fromSelfLoop);
    function fromSelfLoop(element, index, array){
        console.log('checking if sent to Self: ' + element); // 'user1' .. if matches res.locals: (sent from/to Self)
        if (element == res.locals.username) {in = true; console.log('from element: ' + element + ' == res.locals.username: ' + res.locals.username)}
    } // if sent to Self, archive = true

    story.from.push({

        user : res.locals._id,
        username : res.locals.username,
        view :
        {
          inbox: in,
          outbox: true,
          archive: archive,
        },
        updated : req.body.nowDatetime

    });

    story.title = req.body.title;
    // ..even more doc val assignments..

    console.log('To: ' + req.body.to);
    console.log('Story: ' + req.body.title);

    story.save(function(err, result) {

        if (err) {
            console.log(err);
            res.send(err);
        }
        console.log("The result: ", result);
            res.json({ message: 'Story "' + story.title + '" Created' });

    });

    console.log('post success!');

})
4

1 回答 1

2

在我看来,你太过分了,Promises 提供了开箱即用无缝同步的方法。

您可以使用 Promise 聚合方法(在本例中为.join.props)直接映射到属性并获取值。

假设您承诺了 Mongoose(所以 Bluebird 承诺而不是 Mongoose 承诺)。

var story = new Models.Story();
var toArray = req.body.to; // [ 'user1', 'user2', 'user3' ]
var to = Promise.map(toArray,function(element){
    return Promise.props({ // resolves all properties
        user : Models.User.findOneAsync({username: element}), 
        username : element, // push the toArray element
        view : {
            inbox: true,
            outbox: element == res.locals.user.username,
            archive: false
        },
        updated : req.body.nowDatetime
    });
});
var from = Promise.map(toArray,function(element){ // can be a normal map
    return Promise.props({
        user : res.locals._id,
        username : res.locals.username,
        view : {
            inbox: element == res.locals.user.username,
            outbox: true,
            archive: archive,
        },
        updated : req.body.nowDatetime
    });
});
Promise.join(to, from, function(to, from){
    story.to = to;
    story.from = from;
    story.title = req.body.title;
    return story.save(); 
}).then(function(){
    console.log("Success! Story saved!");
}).catch(Promise.OperationalError, function(e){
    // handle error in Mongoose save findOne etc, res.send(...)
}).catch(function(e){
    // handle other exceptions here, this is most likely
    // a 500 error where the top one is a 4XX, but pay close
    // attention to how you handle errors here
});
于 2014-07-11T23:07:43.617 回答