Redis
 sql >> Baza danych >  >> NoSQL >> Redis

Node.js i Redis; Czekam na zakończenie pętli

Pójdę drogą, którą sugerujesz w swoim pytaniu, i dołączę niestandardowe wywołanie zwrotne do funkcji pobierania:

Funkcja
function getStudentsData(callback) {
    var setList = [];
    var dataList = [];

    redisClient.smembers("student_setList", function(err,result) {
        setList = result; //id's of students

        for(var i = 0; i < setList.length; i++) {
            redisClient.get(setList[i], function(err, result) {
                if(err) {
                    console.log("Error: "+err);
                } else {
                    tempObject = JSON.parse(result);
                    if(tempObject.name != null) {
                        dataList.push(tempObject);
                    }
                }
            });     
        }

        if(dataList.length == setList.length) {
            if(typeof callback == "function") {
                callback(dataList);
            }
            console.log("getStudentsData: done");
        } else {
            console.log("getStudentsData: length mistmach");
        }

    });
}

getStudentsData(function(dataList) {
    console.log("Goes here after checking every single object");
    console.log(dataList.length);
    //More code here
});

To prawdopodobnie najskuteczniejsza metoda; alternatywnie możesz polegać na starej szkole while pętla, aż dane będą gotowe:

var finalList = [];
var list = [0];

redisClient.smembers("student_list", function(err,result) {
    list = result; //id's of students
    var possibleStudents = [];

    for(var i = 0; i < list.length; i++) {
        redisClient.get(list[i], function(err, result) {
            if(err) {
                console.log("Error: "+err);
            } else {
                tempObject = JSON.parse(result);
                if(tempObject.name != null) {
                    finalList.push(tempObject);
                }
            }
        });     
    }
});


process.nextTick(function() {
    if(finalList.length == list.length) {
        //Done
        console.log("Goes here after checking every single object");
        console.log(dataList.length);
        //More code here
    } else {
        //Not done, keep looping
        process.nextTick(arguments.callee);
    }
});

Używamy process.nextTick zamiast rzeczywistego while aby upewnić się, że inne żądania nie są w międzyczasie blokowane; ze względu na jednowątkowy charakter JavaScript jest to preferowany sposób. Wrzucam to ze względu na kompletność, ale pierwsza metoda jest bardziej wydajna i lepiej pasuje do node.js, więc zrób to, chyba że w grę wchodzi poważne przepisanie.

To nic nie warte, że oba przypadki polegają na asynchronicznych wywołaniach zwrotnych, co oznacza, że ​​każdy kod poza nim może potencjalnie zostać uruchomiony, zanim inne zostaną skończone. Np. używając naszego pierwszego fragmentu:

function getStudentsData(callback) {
    //[...]
}

getStudentsData(function(dataList) {
    //[...]
});

console.log("hello world");

Ten ostatni plik console.log jest prawie gwarantowany przed uruchomieniem naszego wywołania zwrotnego do getStudentsData. Obejście? Zaprojektuj go, tak właśnie działa node.js. W powyższym przypadku jest to łatwe, po prostu wywołalibyśmy console.log tylko w naszym wywołaniu zwrotnym przekazany do getStudentsData, a nie poza nim. Inne scenariusze wymagają rozwiązań, które odbiegają nieco bardziej od tradycyjnego kodowania proceduralnego, ale kiedy już to opanujesz, przekonasz się, że bycie sterowanym zdarzeniami i brak blokowania jest w rzeczywistości dość potężną funkcją.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Niestandardowe środowisko Railsowe Resque.enqueue nie tworzy zadań

  2. Jak zmusić klienta do pobrania bardzo dużego pliku, który jest generowany w locie?

  3. Redis pisze do .ssh/authorized_keys

  4. Jak uruchomić Redis w systemie Windows?

  5. Jak mogę bezpiecznie połączyć się z Redis hostowanym przez Heroku z wiersza poleceń?