W tym kodzie występują co najmniej dwa problemy:
-
pierwszy jest powiązany z zarządzaniem zamknięciami JavaScript. Treść pętli nie tworzy zakresu. W JavaScript zakres zmiennych jest na poziomie funkcji, a nie na poziomie bloku. Trzeba wprowadzić jakąś funkcję w samej pętli, aby wymusić utworzenie odpowiedniego domknięcia. Więcej informacji tutaj.
-
drugi to wyścig pomiędzy istniejącymi i ustawionymi poleceniami. Jeśli masz kilka uruchomionych połączeń Redis i ustawiasz polecenia na tych samych klawiszach, prawdopodobnie wystąpią pewne konflikty. Zamiast używać istnieje i ustawia, powinieneś użyć setnx, który wykonuje sprawdzenie i ustawienie w jednej atomowej operacji.
Biorąc pod uwagę Twój drugi przykład, problem z zamykaniem został rozwiązany za pomocą forEach, ale nadal generujesz wszystkie operacje get przed operacjami set ze względu na asynchroniczną naturę języka.
Jeśli naprawdę chcesz sekwencjonować wszystkie swoje operacje pobierania i ustawiania (które będą znacznie wolniejsze przy okazji), możesz użyć trochę programowania funkcjonalnego, aby zaimplementować pętlę za pomocą rekurencji.
Przykład :
Ten program:
var redis = require('redis')
var rc = redis.createClient(6379, 'localhost');
var tags = [
"apple",
"tiger",
"mouse",
"apple",
"apple",
"apple",
"tiger",
"mouse",
"mouse",
];
var count = 0;
function loop(tags) {
function rec_loop(tags,i) {
if ( i >= tags.length )
return
rc.get("tag:"+tags[i],function(err,rr) {
console.log("get tag "+tags[i]+" result code "+rr);
if ( rr == null ) {
rc.set("tag:"+tags[i],"info",function(err,rr) {
count++;
console.log('set tag '+tags[i]+' '+rr+' objects count '+count);
rec_loop(tags,++i)
})
} else
rec_loop(tags,++i)
})
}
rec_loop(tags,0)
}
loop(tags)
wyświetla:
get tag apple result code null
set tag apple OK objects count 1
get tag tiger result code null
set tag tiger OK objects count 2
get tag mouse result code null
set tag mouse OK objects count 3
get tag apple result code info
get tag apple result code info
get tag apple result code info
get tag tiger result code info
get tag mouse result code info
get tag mouse result code info
Zauważ, że w tym przykładzie sytuacja wyścigu jest nadal obecna. Powinieneś użyć setnx do zaimplementowania tego rodzaju operacji sprawdzania i ustawiania.