2

В хранилище данных redis У меня есть список ключей, я хочу перебрать этот список ключей и получить эти значения из redis. Загвоздка Я использую событие управляемого язык, JavaScript с помощью Node.jsдля циклического преобразования кода события?

Если JavaScript был процедурным я мог бы сделать это

function getAll(callback) { 
    var list = redis.lrange(lrange('mykey', 0, -1); 
    for (var i = 0; i < list.length; i+= 1) { 
     list[i] = redis.hgetall(list[i]); 
    } 
    callback(list); 
} 

Но я не могу, для этого .. я это делаю?

function getAll(callback) { 
    redis.lrange('mykey', 0, -1, function(err, reply) { 
     // convert reply into messages 
     var list = []; 
     var index = -1; 
     var recurse = function() { 
      if (index == reply.length) { 
       callback(list); 
      } else { 
       redis.hgetall(reply[i], function(err, reply) { 
        list.push(reply); 
        index += 1; 
        recurse(); 
       }); 
      } 
     }; 
     recurse() 
    }); 
}; 

Это швы неправильно, потому что, вместо выполнения всех запросов на один раз, а затем давая обратные вызовы вставки на список, я принуждать последовательную последовательность вызовов. Что произойдет, если есть 1000 ключей?

Могу ли я сделать это как-то?

function getAll(callback) { 
    redis.lrange('mykey', 0, -1, function(err, reply) { 

     // convert reply into messages 
     var list = []; 
     var insert = function(err, reply) { 
      list.push(reply); 
     }; 
     for (var i = 0; i < reply.length; i += 1) { 
      redis.hgetall(reply[i], insert); 
     } 

     ??? how to block until finished ??? 
     callback(list); 
    }); 
}; 
+0

Оба этих ответа велики, барьерный трюк сделал трюк для меня – Daniel

ответ

1

Объявите переменную объекта перед отправкой вызовов в цикле for. Каждый вызов может, чем добавлять его результат в объект.

Для этого вам потребуется код, ожидающий выполнения всех вызовов.Это может помочь вам: https://gist.github.com/464179

Пример:

function getAll(callback) { 

    var results = []; 

    var b = new Barrier(2, function() { 
     // all complete callback 
     callback(); 
     }, function() { 
     // Aborted callback, not used here 
    }); 

    var list = redis.lrange(lrange('mykey', 0, -1); 
    for (var i = 0; i < list.length; i+= 1) { 
     //dispatch your call 
     call(function(foo){ 
      results.push(foo); 
      b.submit(); 
     }); 
    } 
} 

Пожалуйста, обратите внимание, что call() должна быть ваша функция базы данных асинхронной, который выполняет функцию обратного вызова на результат.

3

??? как блокировать до конца ???

Вы не можете, если звонки, которые вы делаете, асинхронны. Вы должны определить свой getAll с ожиданием его завершения асинхронно, а затем немного переделать.

Я не знаком с Redis звонков вы делаете, но основная картина:

function doTheBigThing(param, callbackWhenDone) { 
    asyncCallToGetList(param, function(result) { 
     var list = []; 

     asyncCallToGetNextEntry(result.thingy, receivedNextEntry); 

     function receivedNextEntry(nextResult) { 
      if (nextResult.meansWeAreDone) { 
       callback(list); 
      } 
      else { 
       list.push(nextResult.info); 
       asyncCallToGetNextEntry(result.thingy, receivedNextEntry); 
      } 
     } 
    }); 
} 

Ломая, что вниз:

  1. doBigThing (ваш getAll) называется.
  2. Он выполняет вызов «получить список», передавая функцию, используемую в качестве обратного вызова, когда у нас есть ручка списка или списка или что-то еще.
  3. Этот обратный вызов определяет функцию receivedNextEntry и вызывает функцию «получить следующую запись», используя любую информацию, которая используется для извлечения записи, передавая ее как обратный вызов.
  4. receivedNextEntry сохраняет запись, которую он получил, и, если это сделано, запускает основной «все сделанный» обратный вызов; если нет, он выдает следующий запрос.

К сожалению, не в состоянии дать вам Redis конкретного ответа, но я думаю отображения являются:

  • doBigThing = getAll
  • asyncCallToGetList = redis.lrange
  • asyncCallToGetNextEntry = redis.hgetall

... но какие параметры вы используете с redis.lrange и redis.hgetall Боюсь, я не знаю.

+0

Спасибо! Это определенно помогает! – Daniel

1

Если вам нужно часто использовать такие шаблоны, то вам может быть интересно попробовать async.js library. Использование async.js вы могли бы написать что-то вроде этого:

function getAll(callback) { 
    redis.lrange('mykey', 0, -1, function(err, reply) { 
     async.concat(reply, redis.hgetall, callback); 
    }); 
}; 

Который в основном означает «называть hgetall по каждому пункту„ответ“, то CONCAT всех результатов и передать функцию обратного вызова».