如何在异步NodeJS

时间:2017-08-07 05:46:51

标签: node.js asynchronous callback promise

NodeJS 6.9.3

假设我们使用的是PHP或Ruby等同步语言。我们经常会看到这种模式:

$all_results = [];
$array_of_words = get_relevant_words();

for ($i=0; $i < count($array_of_words); $i++) {

     $word = $array_of_words[$i];

     if (len($word) < 3) {
        continue;
     }

     $results = database_call($word);
     $all_results = array_merge($all_results, $results);    
}

循环数组,进行数据库调用,并且有一些保护子句偶尔会强制代码跳过某些调用 - 这是一种标准模式,你几乎可以在所有代码库中找到它。

由于NodeJS是异步的,我们放弃了某些类型的控制流,我们必须努力让它们恢复。

上周我一直在研究这个问题,我大多数都想知道如何做到这一点,但是我的代码非常难看,我确信必须有一个更惯用的方法来做到这一点。的NodeJS。我很好奇惯用法是什么?

现在,我没有循环,而是递归回调:

    return database_queries.profiles(word, array_of_words_from_string_from_api_call, index_to_read, map_of_profiles)
        .then(function(results_from_database) {

            map_of_profiles = Object.assign( map_of_profiles, results_from_database ); 

            if (index_to_read < array_of_words_from_string_from_api_call.length - 1) {
                return database_queries.profiles(word, array_of_words_from_string_from_api_call, index_to_read + 1, map_of_profiles);

            } else {
                return map_of_profiles; 
            }

该函数一直调用自己,直到索引到达数组中的最后一项。

在数据库查询功能中,我有我的保护条款:

            if (!search_term || search_term == "") {
            var thenable = { then: function(resolve) {
            return new Error ({
                              "message" : "The search term was empty so we did not run the database query.",
                              "array_of_words_from_string_from_api_call" : array_of_words_from_string_from_api_call,
                              "index_to_read" : index_to_read,
                              "map_of_profiles" : map_of_profiles
                              });
            }};
            return thenable; 
            }

这是我的代码开始变得非常难看的地方:我正在传递array_of_words_from_string_from_api_call之类的变量,以便我可以在错误中返回它们,这样它们就可以在catch()块中使用它捕获了这个错误。

最糟糕的是,我没有使用我的catch()块来处理真正的错误,而是复制了上面的所有递归代码,这些代码一直在调用database_queries.profiles()

返回错误是我能找到模仿传统护卫条款的唯一方法。我唯一可以处理此错误的地方是catch块。

在NodeJS中必须有一种不那么难看的方法。谁能告诉我惯用法是什么?

1 个答案:

答案 0 :(得分:2)

一种可能性是使用异步库。它允许您并行或按定义的顺序运行异步代码(当调用相互依赖时)。 看看async documentation

在你的情况下,你可以使用async.each each,它将并行地对数组中的每个元素执行你的函数,最终将调用最终的回调。

在您的情况下,您可以考虑使用eachLimit来限制并行请求的数量,以免数据库因大量请求而崩溃。

const processWords = (words, done, limit = 5) => {
  const results = [];
  async.eachLimit(
    words, // iteratable variable
    limit, // concurrency limit
    (word, next) => { // item processor
      if (word.length < 3) {
        return next();
      }

      database_call(word, (error, result) => {
        if(error) return next(error);
        if(result) results.push(result);
        next();
      });
    }, 
    error => done(error, results) // at the end of iteration
  );
};

const words = ['hello', 'world'];
processWords(words, (error, result) => {
  console.log(error, result);
});