javascript - NodeJS 如何在 Controller 中组织回调

标签 javascript node.js sails.js asynccallback

我是 NodeJS 的新手,来自 PHP 环境,我想弄清楚如何使用多个回调。我确实了解有关回调的基础知识,并且我认为在编写模块时它确实有意义。我的问题是什么时候使用这些模块如何组织所有回调。下面是我实现的请求重置密码 Controller 方法(我使用的是 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');
},

最佳答案

Node.js 回调基础:

大多数功能(Node 及其库(称为模块))具有异步(async)性质。

这些函数有一个共同的签名,回调作为最后一个参数:function(arguments.....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模式也是如此。 future 版本支持generators它提供了许多新的异步模式。

关于javascript - NodeJS 如何在 Controller 中组织回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22393903/

相关文章:

javascript - 自定义组件 - 如何克隆定义为 js 字符串文字的 html 模板?

javascript - Magento 2,链接无效,图像未加载

css - Node.js 不提供 css 文件

node.js - sails.js(v0.11) openshift 需要的墨盒

Node.js - Winston-loggly 模块抛出 "Cannot read property ' length' of undefined”错误

javascript - JQuery - 删除标签脚本

javascript - Bootstrap 模式弹出窗口不显示

node.js - 使用 Angular.js 将 mongoDB 对象中的项目从上到下排列到列表中

node.js - nodejs - 将 Electron 与 ffi 结合使用

node.js - 从策略范围获取 sails 请求目标