从foreach推入数组,并使其在foreach之外可用

时间:2018-12-17 12:29:08

标签: javascript arrays node.js

我陷入了一个循环,该循环遍历一个数组,该数组接收来自promise的值并将值推入一个新数组,该数组在foreach之外可用。

我所拥有的:

   app.post('/submit', function (req, res) {
      uploadPics(req, res, function (err) {
        if (err instanceof multer.MulterError) {
            res.send(JSON.stringify({UploadResult: err.message}));
            console.log(err.message + ' ' +'Redirect /home');
        } else if (err) {
            console.log(err);
        } else {
            res.send(JSON.stringify({UploadResult: 'Success'}));
            var filesarray = req.files;
            var picinfos = [];

            filesarray.forEach(function(file){
                GetFileMetaInfo.filemetainfo(file.path).then(function (metadata){
                    //Stuck here! Can push values into an array (picinfos) but only available in the foreach. not outside..
                })
            })
            //I need picinfos array here....
        }   
    }) 
})

我如何接收元数据:

var exif = require('exif-parser');
var fs = require('fs');


exports.filemetainfo = function (filepath) {
    return new Promise((resolve) => {
        var file = filepath;
        var buffer = fs.readFileSync(file);
        var parser = exif.create(buffer);
        var result = parser.parse();
        resolve (result);
     }).then(function (metadata){
         if (metadata.tags.CreateDate !== undefined){
                date = new Date (metadata.tags.CreateDate*1000);
                datevalues = [
                    date.getFullYear(),
                    date.getMonth()+1,
                    date.getDate(),
                    date.getHours(),
                    date.getMinutes(),
                    date.getSeconds(),
                 ];
                 CreateDate = date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate();
                 CreateTime = date.getHours()+':'+date.getMinutes()+':'+date.getSeconds();
                 console.log("CrDate:" +CreateDate, "CrTime:" +CreateTime );
                } else {
                        console.log("No Metadata Creation Infos found in " +filepath);
                        CreateDate = "";
                        CretaeTime = "";
                }

                if (metadata.tags.GPSLatitude !== undefined){
                    GPSLat = metadata.tags.GPSLatitude;
                    GPSLon = metadata.tags.GPSLongitude;
                    console.log("GPSLat:" + GPSLat , "GPSLon:" +GPSLon); 
                }
                else {
                    console.log("No Metadata GPS Infos found in " +filepath)
                    GPSLat = "";
                    GPSLon = "";
               }
                return MetaData = {
                    GPSLat: GPSLat ,
                    GPSLon: GPSLon,
                    CreateDate: CreateDate,
                    CreateTime: CreateTime,
                    }   
        })
}

我可以请人帮忙吗?我如何才能使阵列在foreach之外可用。非常感谢你!

2 个答案:

答案 0 :(得分:2)

forEach末尾得到空数组的原因是,GetFileMetaInfo.filemetainfo()返回了一个Promise,而forEach不会等待异步操作。

您可以将async/awaitfor...of循环一起使用,以获得所需的结果。

app.post('/submit', function (req, res) {
  uploadPics(req, res, async function (err) { // note async here
    if (err instanceof multer.MulterError) {
        res.send(JSON.stringify({UploadResult: err.message}));
        console.log(err.message + ' ' +'Redirect /home');
    } else if (err) {
        console.log(err);
    } else {
        res.send(JSON.stringify({UploadResult: 'Success'}));
        var filesarray = req.files;
        var picinfos = [];

        for(let file of filesarray) {
          const metadata = await GetFileMetaInfo.filemetainfo(file.path);
          // push metadata into your array here
          picinfos.push(metadata);
        }

        // You will have picinfos here
    }   
  })
})

答案 1 :(得分:0)

尽管问题已经answered by Dinesh Pandiyan,但仍可以进行一些调整。他的答案中的以下代码按顺序运行,这意味着每个异步请求都是在先前返回的结果解析后发出的。

for(let file of filesarray) {
  const metadata = await GetFileMetaInfo.filemetainfo(file.path);
  //                 ^- pauses the execution of the current running code
  // push metadata into your array here
  picinfos.push(metadata);
}
async call #1 ╌╌await╌╌> async call #2 ╌╌await╌╌> async call #3 ╌╌await╌╌> result

您可以通过首先执行所有异步语句,然后等待直到所有结果被解析来使代码并发。只需更改以下内容即可完成此操作:

// execute all the async functions first, reducing the wait time

for(let file of filesarray) {
  const metadata = GetFileMetaInfo.filemetainfo(file.path);
  //                 ^- remove the await
  // push metadata into your array here
  picinfos.push(metadata);
}

// wait for all results to be resolved
picinfos = await Promise.all(picinfos);
//           ^- instead await here
async call #1 ╌╌┐
async call #2 ╌╌┼╌╌await all╌╌> result
async call #3 ╌╌┘

通过将Array.map()与已经显示的Promise.all()结合使用,可以进一步简化上述操作。

var filesarray = req.files;
var picinfos = await Promise.all(filesarray.map(file => {
  return GetFileMetaInfo.filemetainfo(file.path);
}));

// picinfos should be present

或者如果您想避免使用异步/等待:

var filesarray = req.files;

Promise.all(filesarray.map(file => {
  return GetFileMetaInfo.filemetainfo(file.path); 
})).then(picinfos => {
  // picinfos should be present
});