MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Jak obsługiwać wywołania zwrotne w pętli for (Node.JS)

Ten problem jest określany jako "piekło oddzwaniania" .Istnieje wiele innych metod, takich jak użycie Promise i Async biblioteki, które znajdziesz.

Jestem bardziej podekscytowany rodzimymi async ES7 przyniesie, z której możesz zacząć korzystać już dziś dzięki bibliotece transpilera Babel .

Ale zdecydowanie najprostsze podejście, jakie znalazłem, jest następujące:Wyjmujesz długie funkcje zwrotne i definiujesz je na zewnątrz.

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

Zastrzeżeniem jest to, że nie będziesz w stanie uzyskać dostępu do wszystkich zmiennych wewnątrz tego, co kiedyś było wywołaniem zwrotnym, ponieważ wyjęłeś je z zakresu.

Można to rozwiązać za pomocą pewnego rodzaju opakowania „wstrzykiwania zależności”, które przekazuje wymagane zmienne.

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

Zdaję sobie sprawę, że popełniłem tutaj błąd:

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

Kolejny problem, który mógłbym przewidzieć, który w rzeczywistości może nie pojawić się tutaj, ale i tak lepiej byłoby o nim porozmawiać. data zmienna, ponieważ jest to ciąg znaków, który w przeciwieństwie do obiektu jest typem pierwotnym, jest „przekazywana przez wartość”. Więcej informacji

Lepiej jest zawinąć zmienną w obiekt i przekazać obiekt, ponieważ obiekty w javascript są zawsze „przekazywane przez referencję”.

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. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDb :Jak wstawić dodatkowy obiekt do kolekcji obiektów?

  2. Wykonywanie case-statement w ramach agregacji mongodb

  3. Jak utworzyć kanał plików od osób, które obserwuje użytkownik?

  4. 5 sposobów na wstawianie dokumentów do MongoDB

  5. Jaki jest zalecany sposób usuwania indeksów za pomocą Mongoose?