node.js — как передать дополнительные параметры в async.map

#javascript #node.js #asynchronous

#javascript #node.js #асинхронный

Вопрос:

Справочная информация

Я пытаюсь написать какой-нибудь javascript / node.js код, который будет выполнять следующее:

  1. Запросите базу данных redis и получите обратно кучу ключей из моего хэша. Вот как выглядит команда в redis-cli:

    127.0.0.1:6379> hkeys виджеты:1231231234 1) «13:00:00_17:00: 00_mtwrf» 2) «00:00:00_00:00:00» 3) «08:00:00_12:00: 00_mtwrf»

или 127.0.0.1:6379> hkeys виджеты:2222222222 1) «00:00:00_00:00:00»

У каждого виджета будет хотя бы один ключ… вызывается ключ по умолчанию. Ключи по умолчанию выглядят следующим образом: «00:00:00_00:00:00»

Для каждого запроса HKEYS, если возвращается более одного результата, мне нужно проверить каждый возвращенный ключ (кроме значения по умолчанию) на соответствие набору критериев соответствия. Какой бы ключ ни совпадал, он используется для выполнения последующего HGET с redis. Так, например, в первом наборе результатов, показанном выше… Если бы ключ 3 соответствовал, я бы выполнил следующую команду:

 127.0.0.1:6379> hget widgets:2222222222 08:00:00_12:00:00_mtwrf
"some value"
127.0.0.1:6379> 
  

Если ни один из ключей 1 или 3 не совпадает, тогда я запрашиваю ключ по умолчанию.

Код

Недавно я обнаружил модуль async. В настоящее время я использую его в своем коде для перебора результатов из HKEYS. Пожалуйста, посмотрите код ниже:

Код async.map

 router.get('/:widgetnum', function(req, res, next) {
  //validate widgetnum format        
  var widgetnum = req.params.widgetnum;
  if ( !valid_widget(widgetnum) ) {
      var retval = {"res":false, "msg":"malformed widgetnum"};
      res.send(JSON.stringify(retval));
 } else {
      var keys = {};
      redis.hkeys("widgets:"   widgetnum, function(err, data){
          if (err) {
              res.send(JSON.stringify(false));
          }
          if (data) {
             current = getCurrentUTC(); // needed by iterator for match criteria. Using a global variable for now.                                 
            async.map(data, hash_iterator, function (err, iterator_results) {
                  if (iterator_results) {
                      console.log("it are: "   iterator_results);
                  }
                  res.send(iterator_results);
             }); //end async map
          }

      }); //end redis.hkeys
  }
});
  

Вопрос / Проблема

Это работает в том смысле, что для каждого ключа, возвращаемого HKEYS, я могу запустить функцию «hash_iterator».

Однако, оказавшись внутри функции итератора, после оценки / выполнения моих критериев соответствия для каждого результата, у меня нет всей информации, необходимой для запуска вторичного запроса HGET.

Код:

   async.map(data, hash_iterator, function (err, iterator_results)
  

передает только значения:

  "13:00:00_17:00:00_mtwrf"
  "00:00:00_00:00:00"
  "08:00:00_12:00:00_mtwrf"
  

Но мне нужно имя хэша (в данном случае «виджеты:» ) и widgetnum для выполнения вызова HGET.

Я думаю, я могу использовать глобальные переменные… но я хотел убедиться, что мой подход в целом здесь правильный.

Любой ввод был бы оценен.

Вот логика hash_iterator:

 var hash_iterator = function (redis_key, doneCallBack) {
        var results = {};
        console.log("processing..."   redis_key);
        //skip if default rule....
        if (redis_key.indexOf('00:00:00_00:00:00') == -1){
                //need to write logic here to do HGET and save 
                //results somewhere... in case no other keys match 

        } else {
               // run some logic to test match criteria.
              if (matchfound) {
                        console.log("bingo.  found match in "    redis_key);
                        redis.hget(hashname   widgetnum   redis_key, function (e, results){
                          if (results) {
                                return doneCallBack(null, results);
                          } else {
                                 return doneCallBack(null, null);
                          }

                       });                           

                }else {
                        console.log ("no match");
                }
        } 
        return results;
}
  

Комментарии:

1. Я думаю, вы захотите изучить замыкания. Просто определите ту hash_iterator функцию в области видимости, которая имеет доступ к переменной, содержащей ваше "widgets:" значение.

Ответ №1:

Вы можете решить это в функциональном стиле с помощью map. Просто сгенерируйте массив пар, а затем передайте его в async.map , например, из [1,2,3] вы можете сгенерировать [['key', '1'], ['key', '2'], ['key', 3]]

Итак, вот код, который генерирует пары:

 redis.hkeys("widgets:"   widgetnum, function(err, data){
    // some code goes here

    var pairs = data.map(function(ts) {
      return [`widgets:${widgetnum}`, ts];
    });

    // async.map call goes here
}); //end redis.hkey
  

Внутри async.map обратного вызова итератора вы можете получить доступ к ключу с iterator_results[0]

Но в вашем случае переменная widgetnums не является глобальной переменной. Это просто переменная из верхней области видимости, и вы можете использовать ее внутри вложенных функций, если вы определите ее в области propper. Это очень полезный трюк, который называется лексическим замыканием.

Комментарии:

1. извините, я не совсем понимаю этот пример кода. Я думаю, что понимаю ваше вступительное предложение о попытке передать ключ в async.map, но я не понимаю, что такое data.map. Можете ли вы добавить некоторый контекст к этому коду, чтобы сделать его более понятным?

2. Я добавил контекст к своему ответу