今天在根据<node.js开发指南>的书开发个人博客系统的时候,因为mongodb数据库连接的问题debug了好久,页面显示是‘db object already connecting, open cannot be called multiple times’。一开始一直以为是连接数据库的接口出现问题,各种寻找答案未果。
在强哥的帮助下,一步步确定位置错误。因为错误都在db进行open的时候出错,看错误提示应该是数据库已经打开,而未关闭的时候再次发起打开命令。
于是发现在db.open前使用db.close就不会出现错误。所以确定了是数据库未关闭的问题。
可是找了好久,都发现只有一个数据库的实例,并没有进行其他打开操作啊。
注释掉User.get内部代码,无报错;注释掉User.save内部代码,则会报错。说明出错在get内部?
再次回到routes.index的跳转逻辑里,终于发现了问题:
原先的代码如下:
//检查用户存在 User.get(newUser.name, function(err, user){ if(user){ err = '用户名已经存在.'; } if(err){ req.flash('error',err); return res.redirect('/register'); } }); //用户不存在,添加用户 newUser.save(function(err){ if(err){ req.flash('error', err); return res.redirect('/register'); } req.session.user = newUser; req.flash('success', '注册成功'); res.redirect('/'); });
修改后的代码如下:
//检查用户存在 User.get(newUser.name, function(err, user){ if(user){ err = '用户名已经存在.'; } if(err){ req.flash('error',err); return res.redirect('/register'); } //用户不存在,添加用户 newUser.save(function(err){ if(err){ req.flash('error', err); return res.redirect('/register'); } req.session.user = newUser; req.flash('success', '注册成功'); res.redirect('/'); }); });
所以你发现什么区别没有? 答案就是:
newUser.save的位置,它应该放在get的回调函数里的,使得get先执行完(判断用户是否存在),再回调save进行用户没有存在的操作。
而我之前的操作,把save放在get之后的位置,使得get和save是同时执行,数据库当然有绝大可能同时出去open状态了。
这个概念关系到node.js是异步单线程执行的,执行get函数的同时可以立刻执行它之后的函数,等get执行完了再进行回调函数的执行。这下印象更加深刻了。
虽然我很想吐槽,但是关于我是在照着教程敲代码的时候抄错位置了的事情我会乱说出来吗?