Javascript 我想我不知道';";获得;异步编程

Javascript 我想我不知道';";获得;异步编程,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我已经断断续续地使用node.js大约6个月了。但是,我想我仍然不完全理解围绕异步调用设计程序 例如,我的最新程序需要读取配置,使用该配置连接到数据库,然后异步连接到数据库中的每个地址 我正在使用模块和,但这只是伪代码 // first, get the config fnoc(function(err, confs){ // code stuff in here //now check that there's a database config if (confs.has

我已经断断续续地使用node.js大约6个月了。但是,我想我仍然不完全理解围绕异步调用设计程序

例如,我的最新程序需要读取配置,使用该配置连接到数据库,然后异步连接到数据库中的每个地址

我正在使用模块和,但这只是伪代码

// first, get the config
fnoc(function(err, confs){
   // code stuff in here

   //now check that there's a database config
   if (confs.hasOwnProperty("database"))
   {
      // set up db connection
      var mysql_conn = mysql.createConnection({
          host:   confs.database.host,
          user:   confs.database.user,
          password:       confs.database.password,
          database:       confs.database.database
      });
      // do some querying here.
      mysql_conn.query(query, function(err, records, fields){
          records.forEach(function(host){
              // four levels in, and just now starting the device connections
          });
      });


   }
});
每次我用callback-in-in-in-in-of-callback写这样的东西时,我都觉得自己做错了什么。我知道promises和async节点库,但如果这些是解决方案,它们应该是默认功能。是我做错了什么,还是它没有为我点击

编辑:一些建议包括对回调使用函数,但这似乎更糟(除非我做错了,这是完全可能的)。你最终在一个函数中调用另一个函数,它看起来特别像意大利面条

上面的示例包含以下功能:

function make_connection (hosts) {
hosts.foreach(function(host){
      //here's where the fun starts
    };
}


function query_db(dbinfo){
    var mysql_conn = mysql.createConnection({
          host:  dbinfo.host,
          user:  dbinfo.user,
          password:       dbinfo.password,
          database:       dbinfo.database
    });

// do some querying here.
    mysql_conn.query(query, function(err, records, fields){
    make_connection(records);
});

}



// first, get the config
fnoc(function(err, confs){
   // code stuff in here

   //now check that there's a database config
   if (confs.hasOwnProperty("database"))
   {
      // set up db connection

      query_db(confs.database);
      var mysql_conn = mysql.createConnection({
          host:   confs.database.host,
          user:   confs.database.user,
          password:       confs.database.password,
          database:       confs.database.database
      });
      // do some querying here.
      mysql_conn.query(query, function(err, records, fields){
          records.forEach(function(host){
              // four levels in, and just now starting the device connections
          });
      });


   }
});

简而言之:代替

foo(function () {
    // ... stuff #1 ...

    bar(function () {
        // ... stuff #2 ...

        baz();
    });
});

当然,它可以(也可能应该)更细粒度,但这取决于实际代码。这只是一种避免嵌套函数的模式。您还可以更多地封装这些方法


这是“普通”方法。还有一些库允许您以很好的方式管理它。

异步函数和回调的目的是避免对象之间发生任何冲突(可能比您想象的要多!)

我想向您介绍这位异步爱好者:


是的,回调确实需要一些时间来适应,但它是值得的

如果你真的对没完没了的回电感到厌倦,那就试试看。您可以这样编写node.js代码:

co(function *(){
  var a = get('http://google.com');
  var b = get('http://yahoo.com');
  var c = get('http://cloudup.com');
  var res = yield [a, b, c];
  console.log(res);
})()

这几乎是一种不同的编写方式,因此可能很难掌握,但结果非常好。

继续传递样式(适用于此,对吗?)确实需要一些时间来适应。如果您将其正确地拆分为函数,而不是试图将所有内容强制转换为一大块代码,“回调地狱”将变得可管理。意大利面代码总是一种糟糕的模式,不管是回调还是不回调。我觉得它很好。您可以将回调的输出和输入分开,这使得它更易于管理(也更重要)可组合。例如,函数式反应式编程就是这样一种解决方案:。然后,您实际上是在构建电路,数据在其中流动。但是要成为hones,你也需要把你的大脑围绕在它周围,因为它是一个完整的范例,而不仅仅是一个库。我考虑过这一点,但我不会在另一个函数中调用一个函数(比如在config read函数中调用数据库查询函数?)?不知怎么的,它看起来更糟糕。如果做得正确(例如,在封装步骤的“逐步模式”中),它就不是垃圾邮件。是的,函数调用仍然是嵌套的,但这绝对没有错。你可以使用的任何库都会做同样的事情,只是可能“在幕后”。我只同意,有了这样的图书馆,麻省理工学院可能会a)更舒适,b)外观和感觉更干净,即使技术上是一样的。无论如何,适当的分离绝对不是一种反模式。耶,几个月前我和Q做了一些承诺。这很酷,但我觉得在我开始使用快捷方式之前,我应该先了解事情应该如何运作。@coding_hero承诺不是回调的快捷方式,而且工作方式完全不同。事实上,为了从承诺中获得最大的好处,您需要忘记所有关于回调的事情,因为在使用承诺时,任何回调的想法都会导致非常糟糕的代码(这可能是大多数人看不到承诺lol优势的主要原因)。回调的质量很差,任何学习回调的方法都是浪费时间,甚至是有害的——几乎所有其他语言都使用异步承诺,而不是回调。这个博客链接很特别,特别是因为我在做他所说的每一种语言。我会用这个。
co(function *(){
  var a = get('http://google.com');
  var b = get('http://yahoo.com');
  var c = get('http://cloudup.com');
  var res = yield [a, b, c];
  console.log(res);
})()