在两年前的一个 MEAN 技术栈项目中曾经有过这样的一段的代码...
Callback Hell 代码片段
UserLogin.findOne({email:email})
.populate({
path: 'toParty',
select: 'fullname roleTypes'
})
.exec(function(err, result){
if(err)
return res.send(500,{msg:err});
if(result===null)
return res.send(401,{msg:'Malformed Credential'});
loginAudit.userFullname = result.toParty.fullname;
if('normal'!=result.lastStatus){
...
loginAudit.save(function(err){
if(err) return res.send(500,{msg:err});
res.send(401,{msg:'Malformed Credential'});
});
}else{
bcrypt.hash(password, result.salt ,function(err, hash){
if(err)
return res.send(500,{msg:err});
if(result.password!=hash){
...
}else{
...
loginAudit.save(function(err){
if(err) return res.send(500,{msg:err});
...
result.save(function(err){
if(err) return res.send(500,{msg:err});
...
...
}
}
这样的代码段,不仅可读性差,而且可能还会面临像 RangeError: Maximum call stack size exceeded
的问题。
使用 Async.js 进行了重写
async.waterfall([
// step 1
function(next){
UserLogin.findOne({email:email})
.populate({
path: 'toParty',
select: 'fullname roleTypes'
})
.exec(function(err, result){
next(err, result);
})
},
// step 2
function(result, next){
if(!result)
return next(new TuracoError('UserLogin NotFound'));
loginAudit.userFullname = result.toParty.fullname;
if('normal'!=result.lastStatus){
...
}else{
next(null,result);
}
},
// step 3
function(result, next){
bcrypt.hash(password, result.salt ,function(err, hash){
if(err)return next(err);
if(result.password!=hash){
...
}else{
next(null, result);
}
});
},
// step 4
function(result, next){
...
loginAudit.save(function(err){
if(err)return next(err);
...
result.save(function(err){
if(err)return next(err);
...
next(null, token, rs);
});
});
}
// finally
],function(err, token, rs){
if(err){
...
}else{
res.cookie('yourcookiekey',token,{
signed:true,
maxAge:86400000
});
res.send(200,rs);
}
自我感觉好多了:)
从一个坑里爬出来,准备好掉入下一个坑了吗?