在使用 node.js 完成所有承诺后,我想在 mongodb 中插入数据

Posted

技术标签:

【中文标题】在使用 node.js 完成所有承诺后,我想在 mongodb 中插入数据【英文标题】:i want to insert data in mongodb after all promises have been done by using node.js 【发布时间】:2016-05-05 11:02:12 【问题描述】:

我通过使用 Promise 将错误推送到数组中,但在将错误推送到数组之前,它会检查插入数据的条件,就像我正在插入数据一样。

var errorsArr= [];

var username = new Promise(function(resolve,reject)
    User.findOne( "username": req.body.username ,function(err,user)
        if(err)
            reject(err);

        if(user) 
            resolve(1);
        else
            resolve(0);
        
    );
);
username.then(function(data)
    if( data == 1 )
        errorsArr.push("msg": "Username already been taken.");
).catch(function(err)
    console.log(err);
);

var email = new Promise(function(resolve,reject)
    User.findOne( "email": req.body.email ,function(err,user)
        if(err)
            reject(err);

        if(user) 
            resolve(1);
        else
            resolve(0);
        
    );
);
email.then(function(data)
    if( data == 1 )
        errorsArr.push("msg": "email already been taken.");
).catch(function(err)
    console.log(err);
);

if(errorsArr.length >0)

    req.session.error = errorsArr;
    return  res.redirect('/auth/Registration');

else 
    var newUser = new User();
    newUser.username = req.body.username;
    newUser.password = req.body.password;
    newUser.sex = req.body.sex;
    newUser.email = req.body.email;
    newUser.phoneNumber = req.body.phoneNumber;
    newUser.age = req.body.age;
    newUser.designation = req.body.designation;
    newUser.timing = req.body.timing;
    var CurrentDate = moment.tz(new Date(req.body.joiningDate), "Asia/Karachi").unix();
    newUser.joiningDate = CurrentDate;
    newUser.save(function (err, user) 
        if (!err)
            return res.redirect('/auth/Login');
    );

你能帮我以更好的方式做到这一点吗?我是 node.js 的新手。提前致谢。

【问题讨论】:

【参考方案1】:

在完成所有 承诺之后...使用Promise.all

可以编写代码底部的错误检查:

Promise.all([username, email])
.then(function(results) 
    if(errorsArr.length >0)
    
        ...
    
    else 
        ...
    
);

对您的代码进行最快速、最简单的更改 - 重构您的代码可以使其更加流畅

【讨论】:

【参考方案2】:

Promise.all 是您的解决方案。它等待所有的承诺。

 Promise.all([p1,p2,..]).then(function() 
      // all loaded
  , function() 
   // one or more failed
 );

参考链接:

http://www.html5rocks.com/en/tutorials/es6/promises/

【讨论】:

【参考方案3】:

您正在混合异步和同步代码。

同步:

var errorsArr= [];

异步:

var username = new Promise(...
  ...
);
username.then(..
  errorsArr.push(...);
)

同步:

if (errorsArr.length > 0) 
    ...

中间的异步部分(errorsArr.push(…))实际上并没有发生在之前你的同步代码最后(if (errorsArr.length > 0))。

如果您希望它与其他异步代码连续执行,您还需要将所有同步代码转换为异步代码。

其他答案已经解释了如何使用Promise.all

我还想建议使用提供promisification 的Bluebird Promise 库,这样您就可以只承诺您的猫鼬模型,而不是为每个操作手动创建承诺。

Promise.promisifyAll(User);
var username = User.findOneAsync(...); // the new "findOneAsync"  method returns a promise
username.then(data => ...)

您可能还想查看即将在 ES2016 中添加的 javascript 功能,这些功能进一步简化了使用 async/await 的 Promise。有了它,您可以完全摆脱.then(..),只需编写:

app.get('/', async function(req, res)  // < async function
    try 
        var username = await User.findOneAsync(...); // await statements
        var email = await User.findOneAsync(...);
        // do stuff
     catch(err)
        // handle errors
    
);

Checkout this great article on async/await。尽管这需要您使用 Babel 或 Typescript 添加额外的转译步骤。还有最近发布的 Microsoft's fork of Node 附带 chakra 引擎(而不是 V8),它也已经支持 async/await。

【讨论】:

【参考方案4】:

@Jaromanda X 答案是正确的,如果有用户名和电子邮件检查是独立的并且不必遵循顺序。否则,你必须做一个承诺链。

【讨论】:

【参考方案5】:

这是一个例子

  Promise.all([
Reservation.find('parking.owner': req.payload.id).exec(),
Reservation.count('parking.owner': req.payload.id).exec(),
Reservation.aggregate([
    $match: 
        _id: req.payload.id
    ,
     $group: 
        _id: "$_id",
        total:  $sum: "$price"  
    
    ])
  ]).then(results=>
     const list = results[0]
     const count = results[1]
     const sum = results[2]
     res.status(200).json(list,count,sum);
  )

【讨论】:

以上是关于在使用 node.js 完成所有承诺后,我想在 mongodb 中插入数据的主要内容,如果未能解决你的问题,请参考以下文章

Node.js承诺中的readline

带有 API 和数据库查询的 Node.js Promise Chain

完成后逃离承诺链[重复]

node.js 中的异步函数完成后如何运行函数?

使用 jQuery 解决循环中的承诺 [重复]

Node.js Q 承诺,既然可以使用 this(),为啥还要使用 defer()?