NodeJS 搭建开发框架Express,实现Web网站登录验证
MongoDB:更改数据库位置(Windows)
MongoDB在Windows中默认的数据库目录是c:\data。如果在没有该目录的情况下,直接运行mongod.exe,就会报如下错误:
在某些情况下,我们并不想把mongoDB的数据库放在c盘,这时候有两种方法可以切换数据库目录。
1. 命令方式
首先创建数据库目录,例如d:\data。然后运行命令
mongod –dbpath d:\data
2. 配置文件方式
在任意位置创建一个配置文件,例如c:\mongodb\conf的目录下创建一个名为master.cfg的文件,内容为dbpath=d:\data。然后运行命令
mongod –config c:\mongodb\conf\master.cfg
最终输出的结果会类似如下图,表示数据库切换成功:
/
Failed to load c++ bson extension, using pure JS version
I just resolved that.
When you installedinstall the mongoose module by npm, it hasn't builddoes not have a built bson module withinin it's folder. In the file node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/index.js
, chancechange the line
bson = require('../build/Release/bson');
to
bson = require('bson');
and then install the bson module byusing npm.
/
express-session启动警告deprecated undefined resave option
express-session deprecated undefined resave option; provide resave option at app.js:29:9
express-session deprecated undefined saveUninitialized option; provide saveUninitialized option at app.js:29:9
resave - forces session to be saved even when unmodified. (default: true)
resave ——重新保存:强制会话保存即使是未修改的。(默认值ture)
saveUninitialized - forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified. This is useful for implementing login sessions, reducing server storage usage, or complying with laws that require permission before setting a cookie. (default: true)
saveUninitialized——强制“未初始化”的会话保存到存储。一个会话未初始化的时候是新的,但不能修改。这对于实现登陆会话很有用,减少服务器存储的使用,或者服从一种在设置cookie之间的请求规则。。(默认值是true)
用有道翻译的真是晦涩难懂,我的理解是resave:假设每次登陆,就算会话存在也重新保存一次。
saveUninitialized :强制保存未初始化的会话到存储器
Express 报错:Failed to lookup view "error" in views directory 处理
Express框架安装ejs模板的时候,通过在app.js修改
模板为ejs,后缀为html之后发现个别页面打开提示Failed to lookup view "error" in views directory 错误,后面发现是模板里面某个参数没有传入所以出现错误,但是因为views目录下面缺少error文件导致出现这个错误,解决办法就是在模板目录下面创建一个error文件用于输出错误信息。
/
Can't set headers afterthey are sent
[Nodejs] 记录一个小坑:Can't set headers afterthey are sent
exports.Save= function(req, res, next){
varname = req.body.name || "";
if(validator.trim(name).length == 0){
returnRequestError(res, '名称为空');
}
if(req.body._id){
// 修改
Category.update({_id: req.body._id},{$set: {name: name}}, function(err){
if(err)returnMongodbError(res, err);
});
}else{
Category.create({name: name}, function(err){
if(err)returnMongodbError(res, err);
});
}
returnres.json({ success: true,message: '成功' });
好吧,退不出这个黑色的界面了,就这样继续吧~~
Category定义非常简单,只有一个不允许重复的name属性
{
name: {
type: String,
unique: true
}
}
当添加一个重复记录的时候,进程挂掉,报Can't set headers afterthey are sent.错误。之前遇到过这个问题,一般是因为某个res.render,res.send,res.json前面没有return,导致重复调用造成的,但仔细看了几遍上面的代码,该return的地方都return掉了,问题依然存在,什么情况?
在网上乱转的时候看到一条回复提到了异步执行几个字,豁然开朗,之前写c#习惯了能少写一行就少写一行,比如说,上面的代码块,一般来讲,代码应该是这样的,
Category.create(obj, function(err){
if(err){
返回错误
}else{
返回成功
}
})
很多人喜欢这样写:
Category.create(obj, function(err){
if(err) return返回错误
返回成功
})
这样写确实可以省几行代码,也没什么问题,而我却画蛇添足,为了能再省一行,把返回成功的这一句
returnres.json({ success: true,message: '成功' });
抽了出来,放到最后面,这要在其他语言里也并没什么问题,因为err的分支都return掉了,即便写数据库出现错误,也应该会被截止运行,不可能走到最后这一句,然而,我错了,下面的分析是我猜的,说的可能不怎么准确,若有问题,欢迎指正:
假设我们的函数是一个流,正常情况下是顺序执行的,但是当遇到文件io,数据库读写这类任务的时候,node会从这个流程中新建一个分支来执行,而主流程还在继续进行,也就是说按我上面的写法,无论如何都会走到最后一句,res.json一个成功的结果,若写mongodb没问题,也就不会触发err,从而触发res来返回结果,自然不会有问题,但如果写数据库出现err,程序就会找到主流程中的回调方法,而回调中又有一个res.json,自然是多次调用res.json导致程序崩溃。
为此,修改上面的代码做个测试
exports.Save= function(req, res, next){
varname = req.body.name || "";
if(validator.trim(name).length == 0){
returnRequestError(res, '名称为空');
}
setTimeout(function(){
returnres.json({success: true, message: '成功' });
}, 5000);
returnres.json({ success: true,message: '成功' });
}
下面是调用的代码:
$.post("/web/manage/category", {_id: id, name: n.val(), _csrf: csrf}, function (res) {
if (res.success) {
//window.location.reload();
}
console.log(res);
});
运行结果:ajax请求后,返回success:true,几秒钟后,程序崩溃,报Can't set headers afterthey are sent.错误。
解决的办法也很简单,把成功的结果老老实实写到回调函数中就得了。
exports.Save= function(req, res, next){
varname = req.body.name || "";
if(validator.trim(name).length == 0){
returnRequestError(res, '名称为空');
}
if(req.body._id){
// 修改
Category.update({_id: req.body._id},{$set: {name: name}}, function(err){
if(err)returnMongodbError(res, err);
returnres.json({success: true, message: '成功' });
});
}else{
Category.create({name: name}, function(err){
if(err)returnMongodbError(res, err);
returnres.json({success: true, message: '成功' });
});
}
问题解决!!
这个问题对专业nodejs程序员来讲应该是很低级的错误,但对像我一样从其他语言转过来的人来说还是个不大不小的坑,有时候思维定势很可怕,js入门太简单,以至于不愿意定下心来好好的深入的进行研究,往往知其然不知其所以然,引以为戒