是否可以编写异步Node.js代码"清洁"?

ash*_*him 4 asynchronous node.js

在Node.js中进行编码时,我遇到很多情况,因为很难实现与数据库查询(I/O)混合的精细逻辑.

考虑一个用python编写的例子.我们需要遍历一个值数组,对于我们查询数据库的每个值,然后,根据结果,我们需要计算平均值.

def foo:
  a = [1, 2, 3, 4, 5]
  result = 0
  for i in a:
    record = find_from_db(i) # I/O operation
    if not record:
      raise Error('No record exist for %d' % i)
    result += record.value

  return result / len(a)
Run Code Online (Sandbox Code Playgroud)

Node.js中的相同任务

function foo(callback) {
  var a = [1, 2, 3, 4, 5];
  var result = 0;
  var itemProcessed = 0;
  var error;
  function final() {
    if (itemProcessed == a.length) {
      if (error) {
        callback(error);
      } else {
        callback(null, result / a.length);
      }
    }
  }
  a.forEach(function(i) {
    // I/O operation
    findFromDb(function(err, record) {
      itemProcessed++;
      if (err) {
        error = err;
      } else if (!record) {
        error = 'No record exist for ' + i;
      } else {
        result += record.value;
      }
      final();
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

您可以看到这样的代码更难写/读,并且更容易出错.我的问题:

  1. 有没有办法使Node.js上面的代码更清晰?
  2. 想象一下更复杂的逻辑.例如,当我们从db获取记录时,我们可能需要根据某些条件执行另一个db查询.在Node.js中成为一场噩梦.处理此类任务的常见模式是什么?
  3. 根据您的经验,使用Node.js进行编码时,性能提升是否值得降低生产力?
  4. 是否有其他更易于使用的异步I/O框架/语言?

msc*_*dex 5

回答你的问题:

  1. 有些库async可以在处理异步任务时为常见场景提供各种解决方案.对于"回调地狱"问题,有很多方法可以避免这种情况,包括(但不限于)命名您的功能并将其拉出来,模块化您的代码以及使用承诺.

  2. 或多或少你现在拥有的是一个相当常见的模式:具有一个函数数组的计数器和函数索引变量.再次,async可以在这里提供帮助,因为它可以减少您经常会经常重复的这种样板.async目前没有真正允许跳过单个任务的方法,但如果你正在编写样板文件,你可以自己轻松地做到这一点(例如,只需将函数索引变量增加2).

  3. 根据我自己的经验,如果你正确设计你的javascript代码并考虑异步,并使用很多工具async,你会发现用节点开发更容易.在节点中编写异步与同步通常总是会更复杂(尽管与回调/承诺相比,生成器,光纤等更少).

  4. 我个人认为决定基于单一方面的语言是不值得的.您必须考虑的不仅仅是语言的设计,例如社区的大小,第三方库的可用性,性能,技术支持选项,代码调试的简易性等.