sql >> Databasteknik >  >> NoSQL >> MongoDB

Hur man hanterar återuppringningar i en for-loop (Node.JS)

Det här problemet kallas "återuppringningshelvetet" . Det finns många andra metoder som att använda Promise och Async bibliotek du hittar.

Jag är mer exalterad över den infödda code>async ES7 kommer att ta med, som du faktiskt kan börja använda idag med transpilerbiblioteket Babel .

Men den överlägset enklaste metoden jag har hittat är följande:Du tar bort de långa återuppringningsfunktionerna och definierar dem utanför.

router.route('/report') // the REST api address
    .post(calling_a_POST)

function calling_a_POST(req, res) {
    ...
    var data = "";
    https.get(url, function callback(response) {
        ...
        response.on("end", response_on_end_callback); // --> take out
        response.on("error", console.error);
    });
}

function response_on_end_callback() {                 // <-- define here
    ...
    for (var i = 0; i < length; i++) {
        var report = new Report(array.pop());
        ...
        Report.find({ id: report['id'] })
              .count(Report_find_count_callback);     // --> take out
    };
    res.json({
        message: 'Grabbed Report'
    });
}

function Report_find_count_callback(err, count) {     // <-- define here
    ...
    if (count == 0) {
        report.save(function(err) {                   // !! report is undefined here
            console.log('saved');
            if (err)
                res.send(err);                        // !! res is undefined here
        });
    }
}

En varning är att du inte kommer att kunna komma åt alla variabler i det som brukade vara återuppringningen, eftersom du har tagit dem utanför räckvidden.

Detta skulle kunna lösas med en sorts "beroendeinjektion" för att skicka de nödvändiga variablerna.

router.route('/report') // the REST api address
    .post(calling_a_POST)

function calling_a_POST(req, res) {
    ...
    var data = "";
    https.get(url, function callback(response) {
        ...
        response.on("end", function(err, data){       // take these arguments
            response_on_end(err, data, res);          // plus the needed variables
        });
        response.on("error", console.error);
    });
}

function response_on_end(err, data, res) {  // and pass them to function defined outside
    ...
    for (var i = 0; i < length; i++) {
        var report = new Report(array.pop());
        ...
        Report.find({ id: report['id'] })
            .count(function(err, count){
                Report_find_count(err, count, report, res);  // same here
            });
    };
    res.json({                                        // res is now available
        message: 'Grabbed Report'
    });
}

function Report_find_count(err, count, report, res) {        // same here
    ...
    if (count == 0) {
        report.save(function(err) {                   // report is now available
            console.log('saved');
            if (err)
                res.send(err);                        // res is now available
        });
    }
}

Jag inser att jag gjorde ett fel här:

function calling_a_POST(req, res) {
    ...
    var data = "";
    https.get(url, function callback(response) {
        ...
        //sponse.on("end", function(err, data){
        response.on("end", function(err){ // data shouldn't be here
            response_on_end(err, data, res);
        });
        response.on("error", console.error);
    });
}

Ett annat problem jag kunde förutse, som faktiskt kanske inte uppstår här men som ändå skulle vara bättre att prata om. data variabel, eftersom det är en sträng som är en primitiv typ till skillnad från ett objekt, "passeras den av värde". Mer information

Det är bättre att linda variabeln i ett objekt och skicka objektet, eftersom objekt i javascript alltid "passeras med referens".

function calling_a_POST(req, res) {
    ...
    // var data = ""; // 
    var data_wrapper = {};
    data_wrapper.data = {};                                // wrap it in an object
    https.get(url, function callback(response) {
        ...
        response.on("data", function(chunk){
            data_wrapper.data += chunk.toString() + "";   // use the dot notation to reference
        });
        response.on("end", function(err){ 
            response_on_end(err, data_wrapper, res);      // and pass that object
        });
        response.on("error", console.error);
    });
}

function response_on_end_callback(err, data_wrapper, res) {
    var data = data_wrapper.data;                         // later redefine the variable
    ...
    for (var i = 0; i < length; i++) {
        var report = new Report(array.pop());
        ...


  1. Integrering av ClusterControl med SNMP:Del två

  2. Hur ansluter man till MongoDB 3.2 i Java med användarnamn och lösenord?

  3. Mongodb-fråga baserad på objekt vid specifik position i arrayen

  4. MongoDB-objekt serialiserat som JSON