2016-09-01 224 views
0

我正在與Nodejs和我想使用承諾,以便作出for循環後的完整響應。NodeJS異步與Q承諾

exports.getAlerts = function(req,res,next){ 
var detected_beacons = []; 
if (!req.body || Object.keys(req.body).length == 0) { 
    res.status(401); 
    res.json({message:'No data sent'}); 
    return 
} 
var nets = req.body.networks; 
db.collection("beaconConfig", function(err, beaconConfigCollection){ 
    if (!err){ 
     var promises = []; 
     for(var i=0;i<nets.length;i++){ 
      var defer = q.defer(); 
      beaconConfigCollection.find({$or: [{"data.major" : nets[i].toString()},{"data.major" : nets[i]}], batteryLevel : {$lt : 70}}).toArray(function(errFind, saver){ 
       if (!errFind && saver && saver.length > 0){ 
        promises.push(defer.promise); 
        console.log("--------------------savers -------------------"); 
        console.log(saver); 
        for(var j=0; j<saver.length;j++){ 
         console.log("--------------------saver[j]-------------------"); 
         console.log(saver[j]); 
         var detected = {} 
         var major = saver[j].data.major; 
         detected.major = major; 
         console.log("--------------------detected -------------------"); 
         console.log(detected); 
         detected_beacons.push(detected); 
         defer.resolve(detected); 
        } 
       } 
      }); 
     } 
     q.all(promises).then(function(results){ 
      console.log("--------------------detected_beacons -------------------"); 
      console.log(detected_beacons); 
      res.json(detected_beacons); 
     }); 

    } else { 
     console.error(err); 
     res.status(500); 
     res.json({message:"Couldn't connect to database"}); 
    } 
});}; 

所有consoles.log工作正常,除非最後一個,--- detected_beacons ---一個,這是第一個要顯示,它是空的。

這就是爲什麼我認爲承諾運作不好的原因。我有var q = require('q');在頂部,並且mongo連接不會返回任何問題。

感謝您的幫助。

+2

因爲'promise'數組是異步填充的。 – thefourtheye

+0

我該如何解決這個問題? – aserrin55

+1

嗯,只是把'promises.push(defer.promise);'異步回調之外?順便說一句,你也得到了[迴路問題中的常見閉包](http://stackoverflow.com/q/750486/1048572)。在一個單獨的函數中更好地將'find'的[promsification](因爲它包含在http://stackoverflow.com/q/22519784/1048572)中。 – Bergi

回答

1

首先,awesome guide關於如何與承諾相處。

好吧,討厭的人會討厭,但Promises根本沒有錯(至少我希望如此)。

根據'MongoDb for Node' documentation.toArray()返回一個Promise,就像這個庫的大多數方法一樣。我覺得可以隨意在你的代碼上做一些約會:

exports.getAlerts = function(req, res, next) { 
    if (!req.body || Object.keys(req.body).length == 0) { 
     res.status(401); 
     res.json({message: 'No data sent'}); 
     return; 
    } 
    // db.collection returns a promise :) 
    return db.collection("beaconConfig").then(function(beaconConfigCollection) { 
     // you can use .map() function to put together all promise from .find() 
     var promises = req.body.networks.map(function(net) { 
      // .find() also returns a promise. this promise will be concat with all 
      // promises from each net element. 
      return beaconConfigCollection.find({ 
       $or: [{ 
        "data.major": net.toString() 
       }, { 
        "data.major": net 
       }], 
       batteryLevel: { 
        $lt: 70 
       } 
      }).toArray().then(function(saver) { 
       // you can use the .find() response to create an array 
       // with only the data that you want. 
       return saver.map(function(saverElement) { 
        // your result array will be composed using saverElement.data.major 
        return saverElement.data.major; 
       }); 
      }).catch(function(err) {}); 
     }); 
     // use q.all to create a promise that will be resolved when all promises 
     // from the array `promises` were resolved. 
     return q.all(promises); 
    }).then(function(results) { 
     console.log("results", results); 
    }).catch(function(err) {}); 
}; 

我希望它可以幫助你!