【问题标题】:How to avoid callback hell in nodejs for sequelize如何避免nodejs中的回调地狱以进行续集
【发布时间】:2014-11-18 18:14:01
【问题描述】:

我正在使用 Sequelize 并最终陷入回调地狱:

db.Role.findAll().success(function(roles) {
            db.User.findAll({where: {permission: 'coach'}}).success(function(coaches) {
                res.render('users/edit_profile', {successFlash: successFlash, user: user, roles: roles, coaches: coaches});
            }).error(function(errors) {
                console.log("Error", errors);
                res.render('dashboard', {successFlash: successFlash, errors: errors});
            });
        }).error(function(errors) {
            console.log("Error", errors);
            res.render('dashboard', {successFlash: successFlash, errors: errors});
        });

我想避免回调地狱并使代码更可重用。有没有办法在不使用异步、承诺等的情况下做到这一点?

假设我写了这样的东西..

get_user: function(req, res) {
    var users = null;
    users = func.get_users();
    res.render('users/get_users', {users: users});
}

get_users: function() {
        db.User.findAll().success(function(users){
            return users;
        }).error(function(err){
            return null;
        });
    }

这种方法的问题在于,get_user 先渲染页面,然后执行来自get_users 的回调,给我的用户总是 null。

请在这方面帮助我!

提前致谢!

【问题讨论】:

  • 回调地狱?在哪里?我很确定回调地狱通常是指您在回调(...等)内部的回调内部有回调的地方。你有 promise 风格的回调,这可能和你得到的一样好。如果你不喜欢回调,我不会推荐一个涉及大量使用回调的框架。
  • 感谢您的反馈。我担心的是,我想让代码更可重用。使用上面的第一种方法,如果我要在控制器中编写另一个函数,我会再次编写所有查询(可能顺序会有所不同)。我想将所有查询放在一个单独的控制器中,在不同的函数中,然后只调用其他控制器中的函数。我希望,你明白我的意思。 :)

标签: node.js callback sequelize.js


【解决方案1】:

Sequelize 2.0 附带原生 Promise,因此您无需在代码中手动要求 Promise 库。在 2.0 中,您的 sn-p 可以写成:

db.Role.findAll().bind({}).then(function(roles) {
  this.roles = roles;

  return db.User.findAll({where: {permission: 'coach'}});
}).then(function(coaches) {
  res.render('users/edit_profile', {successFlash: successFlash, user: user, roles: this.roles, coaches: coaches});
}).catch(function(errors) {
  console.log("Error", errors);
  res.render('dashboard', {successFlash: successFlash, errors: errors});
});

您只需要一个 catch 块,因为当您 return 一个承诺时,任何错误都会传播到链的顶部。

bind({}) 部分在您的 Promise 链中的所有函数中提供一个空对象,因此您可以通过这种方式传递上下文。如果你也可以做bind(this),如果你希望能够从外部上下文访问某些东西,而不必做惯用的var self = this

【讨论】:

    【解决方案2】:

    试试这个:

      get_user: function(req, res) {
        var users = null;
        func.get_users(function(result){
          if (result==null) //handle error
          res.render('users/get_users', {users: users});
       });
    }
    
    get_users: function(callback) {
            db.User.findAll().success(function(users){
                callback(users);
            }).error(function(err){
                callback(null);
            });
        }
    

    【讨论】:

    • 谢谢。这行得通!从我发布的第一个代码 sn-p 开始,假设我想先获取所有角色,然后是用户,我该如何重构代码?
    猜你喜欢
    • 2017-08-18
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    相关资源
    最近更新 更多