MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Cara menangani panggilan balik dalam for loop (Node.JS)

Masalah ini disebut sebagai "callback hell" .Ada banyak pendekatan lain seperti menggunakan Janji dan Async perpustakaan yang akan Anda temukan.

Saya lebih senang dengan async ES7 akan dibawa, yang sebenarnya dapat Anda mulai gunakan hari ini dengan pustaka transpiler Babel .

Tetapi sejauh ini pendekatan paling sederhana yang saya temukan adalah sebagai berikut:Anda mengambil fungsi panggilan balik yang panjang dan mendefinisikannya di luar.

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

Peringatan adalah bahwa Anda tidak akan dapat mengakses semua variabel di dalam apa yang dulunya merupakan panggilan balik, karena Anda telah mengeluarkannya dari ruang lingkup.

Ini dapat diselesaikan dengan semacam pembungkus "injeksi ketergantungan" untuk meneruskan variabel yang diperlukan.

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

Saya menyadari bahwa saya membuat kesalahan di sini:

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

Masalah lain yang dapat saya perkirakan, yang sebenarnya mungkin tidak muncul di sini tetapi tetap lebih baik untuk dibicarakan. data variabel, karena ini adalah string yang merupakan tipe primitif tidak seperti objek, itu "dilewati oleh nilai". Info lebih lanjut

Lebih baik membungkus variabel dalam sebuah objek dan meneruskan objek tersebut, karena objek dalam javascript selalu "dilewati oleh referensi".

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. Meteor mongo memperbarui susunan bersarang

  2. Penghitungan agregasi objek bersarang MongoDB

  3. Instansiasi kacang gagal :Kelas yang ditentukan adalah antarmuka

  4. Bagaimana cara menyimpan dokumen dalam agregasi dengan $unwind

  5. mendapatkan kesalahan ReplicaSetNoPrimary dan MongoServerSelectionError saat menghubungkan MongoDB dengan nodejs