NodeJS如何在控制器中组织callback

我是新来NodeJS和来自PHP环境我想弄清楚如何使用多个callback。 我确实了解callback的基础知识,我认为在编写模块时确实很灵敏。 我的问题是什么时候使用这些模块如何组织所有的callback。 下面是我的实现一个请求重置密码控制器方法(我正在使用SailsJS)。 这是我的代码的初稿。 主要是testing一个组织callback的方法。 你们如何看待这种结构? 有没有更好的办法呢?

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'); }, 

Node.jscallback基础:

大多数function(节点及其库(称为模块))具有asynchronous(asynchronous)性质。

这些函数与callback作为最后一个参数有一个共同的签名: function(arguments.....callback)

callback只是另一个JavaScript函数。 (是的,在Javascript中,函数可以作为parameter passing给其他函数)。 Node.js典型的callback函数具有第一个参数作为错误(如果发生的话)的签名: callback(err,outputs......)

例如:第一个参数是一个string,第二个是一个对象(内联定义),最后一个是一个函数(内联定义)。

 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); 

所以这里的基本合同是给它的参数赋予一个函数,并在完成时传递一个callback被调用。 传入的callback函数将会在将来有时候返回,错误或者结果的地方被调用。

多个嵌套的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这样的模块可以帮助组织callback:

 function uploadAll(path,callback){ async.waterfall( [ function(cb){ listFiles(path,cb); }, function(files,cb){ async.map(files,uploadFile,cb); } ],callback); } 

此外,还有Promises模式。 未来版本支持提供许多新的asynchronous模式的生成器 。

您可以使用asynchronous或q来pipe理callback金字塔