我是NodeJS的新手,来自PHP环境我试图弄清楚如何使用多个回调。我确实理解了关于回调的基础知识,我认为在编写模块时它确实很有意义。我的问题是什么时候来使用这些模块如何组织所有的回调。下面是我的实现请求重置密码控制器方法(我正在使用SailsJS)。这是我的代码的初稿。它主要是测试一种组织回调的方法。你们怎么看待这个结构?有更好的方法吗?
var _ = require('lodash');
var moment = require('moment');
var mailer = require("../../services/Mailer");
var crypto = require('../../services/crypto');
var forms = require("forms"),
fields = forms.fields,
validators = forms.validators;
module.exports = {
// Request reset user password: submit form and send email
request_process : function(req, res, next) {
var form = createForm();
form.handle(req, {
// there is a request and the form is valid
// form.data contains the submitted data
success: function (form) {
var user = null;
var username = form.data.username;
User.findOne({'username' : username}, foundUser);
function foundUser( err, _user){
if(err)
res.send(500, 'User not found');
user = _user;
if user.isPasswordRequestNonExpired()
return res.view('user/resetting/passwordAlreadyRequested');
if !user.passwordRequestToken
user.passwordRequestToken = crypto.randomToken();
renderEmail(null, user);
}
function renderEmail(err, user){
res.render('email/resetting_check_email', {'user': user, }, sendEmail );
}
function sendEmail(err, template){
if(err)
return res.send(500, "Problem with sending email");
Mailer.send( user, "Reset Password", template, sentEmail);
}
function sentEmail(err, response){
if(err)
return res.send(500, "Error sending email");
user.passwordRequestedAt = moment().format();
user.save(finish);
}
function finish(err){
if(err)
return res.send(500);
res.view();
}
},
// the data in the request didn't validate,
// calling form.toHTML() again will render the error messages
error: function (form) {
console.log("registration error", form);
res.locals.form = form;
return res.render('user/registration/register');
},
// there was no form data in the request
empty: function (form) {
console.log("registration empty", form);
res.locals.form = form;
return res.render('user/registration/register');
}
},
// Tell the user to check his email provider
check_email : function(req, res, next) {
// if empty req.params.email
// redirect request view
// res.view('check_email.ejs')
},
// Reset user password
reset : function(req, res, next){
// find userByPasswordToken
// if !user
// res.view ('invalid or expired "confirmation token".')
// user.update password
// res.view('reset.ejs');
},
答案 0 :(得分:2)
Node.js回调基础:
大多数功能(节点及其库(称为模块))具有异步(异步)特性。
这些函数有一个共同的签名,回调作为最后一个参数:function(arguments.....callback)
。
callback
只是另一个JavaScript函数。 (是的,在Javascript中,函数可以作为参数传递给其他函数)。 Node.js典型的回调有一个签名,第一个参数为错误(如果有的话):callback(err,outputs......)
。
示例:第一个参数是一个字符串,第二个是对象(内联定义),最后一个是函数(内联定义)。
doSomeWork('running',{doFast:true,repeat:20}, function(err,result){
if(err){
console.log('ohnoes!);
} else {
console.log('all done : %s',result);
}
});
相当于:
var type = 'running';
var options = {doFast:true,repeat:20};
var callback = function(err,result){
if(err){
console.log('ohnoes!);
} else {
console.log('all done : %s',result);
}
};
doSomeWork(type,options,callback);
所以这里的基本契约是给函数一个参数,并在完成后传递一个回调函数。传递的回调将在以后有什么地方可以调用时返回,错误或结果。
多个嵌套回调通常不太可读和复杂:
function uploadAll(path,callback){
listFiles(path,function(err,files){
if(err){
callback(err);
}else{
var uploaded = [];
var error;
for(var i = 0 ; i < files.length; i++){
uploadFile(files[i],function(err,url){
if(err){
error = err;
break;
}else{
uploaded.push(url);
}
});
}
callback(error,uploaded);
}
});
};
但幸运的是,有async
这样的模块可以帮助组织回调:
function uploadAll(path,callback){
async.waterfall(
[
function(cb){
listFiles(path,cb);
},
function(files,cb){
async.map(files,uploadFile,cb);
}
],callback);
}
此外,还有Promises
模式。未来版本支持generators,它提供了许多新的异步模式。
答案 1 :(得分:1)