Redis
 sql >> Database >  >> NoSQL >> Redis

Node.js e Redis; In attesa che un ciclo finisca

Vorrei seguire la strada che suggerisci nella tua domanda e allegare una richiamata personalizzata alla tua funzione di recupero:

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
});

Questo è probabilmente il metodo più efficiente; in alternativa potresti fare affidamento su una vecchia scuola while ciclo finché i dati non sono pronti:

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);
    }
});

Usiamo process.nextTick invece di un vero while per assicurarsi che altre richieste non siano bloccate nel frattempo; a causa della natura a thread singolo di Javascript, questo è il modo preferito. Lo sto inserendo per completezza, ma il primo metodo è più efficiente e si adatta meglio a node.js, quindi provalo a meno che non sia coinvolta una riscrittura importante.

Non vale nulla che entrambi i casi si basino su callback asincroni, il che significa che qualsiasi codice al di fuori di esso può ancora essere potenzialmente eseguito prima che altri vengano eseguiti. Ad esempio, utilizzando il nostro primo snippet:

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

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

console.log("hello world");

È quasi garantito che l'ultimo console.log venga eseguito prima che il nostro callback passato a getStudentsData venga attivato. Soluzione alternativa? Progetta per questo, è proprio come funziona node.js. Nel nostro caso sopra è facile, chiameremo console.log solo nel nostro callback passato a getStudentsData e non al di fuori di esso. Altri scenari richiedono soluzioni che si discostino un po' di più dalla codifica procedurale tradizionale, ma una volta che ci avrai capito, scoprirai che essere guidati dagli eventi e non bloccanti è in realtà una funzionalità piuttosto potente.