异步添加到Nodejs数组

Asynchronous add to array in Nodejs

本文关键字:数组 Nodejs 添加 异步      更新时间:2023-09-26
 var veh = [];
 app.get('/updateProf', isLoggedIn, function(req, res) {

     for (var i = 0; i < req.user.local.vehicles.length; i++){
           Vehicles.findById(req.user.local.vehicles[i], function(err, vehicle) {
              veh.push(vehicle);
              console.log("GET Json: " + veh);
            });
     }
     console.log(veh);
     res.json(veh);
     veh.length = 0;
});

所以我正在做一个get请求来获取我所有的车辆,用户拥有并返回它的json,刷新后它工作得很好,但是当我去到页面时,它在初始加载时显示一个空数组,如果我刷新页面,该数组被填充。我认为这个问题与它是异步的有关,但是我很难这样想,需要一些关于如何解决这个问题的建议。

是的!

在返回JSON之前,您必须等待所有回调完成。

一个解决方案是保持有多少回调被执行的计数,当它们都被执行时,你可以返回JSON。

 var veh = [];
 app.get('/updateProf', isLoggedIn, function(req, res) {
 number_processed = 0;
 total = req.user.local.vehicles.length;
 for (var i = 0; i < req.user.local.vehicles.length; i++){
       Vehicles.findById(req.user.local.vehicles[i], function(err, vehicle) {
         if(!err){
             veh.push(vehicle);
         }
         number_processed  = number_processed  + 1;
         if(number_processed === total){
             res.json(veh);
         }
         console.log("GET JSON: " + veh);
      });
 }
 veh.length = 0;
 });

如果您使用的是最新版本的Mongoose,那么您可以直接使用Mongoose为每个查询返回的Promises

例如,您的查询可以简化为

Vehicles.find({ _id: {'$in': req.user.local.vehicles }})
  .exec()
  .then(function(vehicleArr) {
    res.json(vehicleArr);
  });

请注意,我使用$in操作符将循环直接转换为IN条件,该条件接受您想要比较的数组(在本例中,它是一个id数组)

then()函数只在查询完成时执行。

Async是一个处理此问题的实用程序库。

 var async = require('async');
 app.get('/updateProf', isLoggedIn, function(req, res) {
   async.map(req.user.local.vehicles, function(vehicle, cb){
     Vehicles.findById(vehicle, function(err, vehicle) {
       if (err) cb(err, null);
       console.log('GET Json: ' + vehicle);
       cb(null, vehicle);
     });
   }, function (err, results) {
     console.log(results);
     res.json(results);     
   });
});