我正在使用 NodeJS 创建一个快速端点,该端点将从存储在我的服务器上的图像中检索元数据。我有以下端点逻辑代码:
/*
* Gallery Controller
*/
var fs = require('fs'),
_ = require('underscore'),
im = require('imagemagick');
/**
* List paths to images stored in selected gallery
*/
exports.list = function(req, res) {
var dir = 'public/images/' + req.params.id;
fs.readdir(dir, function(err, files) {
if (err) return res.send({error: 'No gallery found with provided id'}, 404);
if (files.length > 0) {
var collection = [],
myData = {};
files.forEach(function(file) {
if(file === '.DS_Store') return;
im.readMetadata( dir + '/' + file, function(err, metadata) {
if (err) throw err;
myData = metadata;
console.log(myData); // logs as object with expected data
});
console.log(myData); // logs as empty {}
collection.push(myData);
});
console.log(collection); // logs as [ {}, {} ]
res.json(collection, 200);
} else {
res.json({error: 'Selected gallery is empty'}, 404);
}
});
};
我已经列出了日志在终端中显示的内容,为什么我会遇到此范围问题?我似乎无法理解它。如果我尝试返回
metadata
obj并将其分配给var
,我会收到以下错误:TypeError:转换循环结构转为 JSON
最佳答案
使用async模块,它将在很多方面改善您的生活。
您遇到的问题是我看到的一个常见问题,它是您的循环是异步的,但您将其视为串行的东西。
您不想执行files.forEach
,而是希望异步循环它们,然后在循环完成后执行更多操作。您可以使用async.each
来实现。
async.each(files, function (file, next) {
if (file === '.DS_Store') return next();
im.readMetadata(path.join(dir, file), function (e, data) {
collection.push(data);
next(err);
});
}, function (err) {
if (err) throw err;
console.log(collection);
});
作为替代方案,更合适的解决方案可能是使用 async.map
。
async.map(files, function (file, next) {
if (file === '.DS_Store') return next();
im.readMetadata(path.join(dir, file), next);
}, function (err, collection) {
if (err) throw err;
console.log(collection);
});
关于Javascript 作用域问题,对象在分配后没有数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20304554/