Javascript作用域问题,对象在分配后没有数据
Javascript scoping issue, object has no data after assigning it
我正在使用NodeJS创建一个express端点,该端点将从存储在服务器上的图像中检索元数据。我有以下端点逻辑代码:
/*
* 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);
}
});
};
我已经列出了日志在终端中的显示方式,为什么我会遇到这个范围界定问题?我似乎无法理解它。如果我尝试return
metadata
obj并将其分配给var
,我会得到以下错误:TypeError: Converting circular structure to JSON
使用异步模块,它将在许多方面改善您的生活。
我看到你遇到的问题很常见,那就是你的循环是异步的,但你把它当作串行的。
您不想执行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);
});
您需要重组您的代码:
files.forEach(function(file, i) {
if (file === '.DS_Store') return; // see text
im.readMetadata( dir + '/' + file, function(err, metadata) {
if (err) throw err;
collection.push(metadata);
if (i === files.length - 1) {
res.json(collection); // see text
}
});
});
原因是只有当调用readMetadata
的回调函数时,元数据才可用;这就是Node中异步I/O的工作方式。
在该回调中,您将元数据添加到集合中。如果forEach
的迭代已经到达最后一个元素(i
是当前元素的索引,当它的值比数组的大小小一时,它是最后一个元件),则发送响应。
两个问题:
- 如果
.DS_Store
是目录中最后一个/唯一的文件,则此代码将失败,因为它永远不会发回响应;我交给你来处理那个案子;) - 默认情况下,
res.json
将返回200
状态,因此您不必指定它;如果确实要指定状态,则该状态需要为res.json(200, collection)
(已交换参数)
相关文章:
- 将节点数据分配给另一个变量jstree
- 比较和分配数据类型的困难
- 是否可以使用CSS分配数据属性
- 如何将HTML表单(JSON格式)中的数据分配给变量
- 在将csv文件中的数据分配给数组变量时增强了d3代码
- Node.js,为事件分配回调函数'数据'
- 将 Ajax 数据分配给全局变量时出现问题
- ExtJS:为存储中的数据分配一个变量
- 如何使用ajax将检索到的数据分配给不同的td
- 严格模式下的图像数据数据分配
- 根据数据类型动态为Highcharts中的特定数据分配颜色
- AngularJS:将$http.get数据分配给变量
- 如何将从$promise返回的数据分配给全局变量
- 当您将字符串文本传递给变量,然后将该字符串中的数据分配给新变量时,它叫什么
- React/Rect Native无法将JSON数据分配给状态变量
- Javascript:将数据分配给多维数组
- d3.js无法将加载的json数据分配给变量
- 使用Firefox API将剪贴板数据分配给本地变量
- Ajax成功数据分配给数据为[0]的变量是未定义的
- 将JSON数据分配给变量并通过React中的状态访问它时出错