【发布时间】:2017-08-28 11:42:32
【问题描述】:
我已经阅读了this post,但我的问题不是那个。我正在编写 mongoDB GridFS 管理所需的函数。我遇到了一个非常奇怪的行为,我将向您展示一个简化的示例。如您所知,我们经常使用回调函数。在我的简化示例中,一切正常。问题是我想用来自回调函数的值更新一个局部变量:
function secondFunction(input, callbackFunction) {
var result = input + 5;
callbackFunction(result);
}
function thirdFunction(input, callbackFunction) {
var result = input + 5;
callbackFunction(result);
}
function mainFunction(input) {
var Answer = 0;
secondFunction(input, function (result) {
thirdFunction(result, function (result) {
Answer = result;
})
});
console.log(Answer);
}
mainFunction(5);
如您所料,结果为 15。Answer 全局变量已成功更新。但我的问题是下面的代码似乎局部变量没有改变。在这个例子中,我想从 gridFS 中一张一张地获取我的图像并将它们推送到一个名为 images 的数组中(这是局部变量):
function getAll(callback) {
var images = [];
db.collection('fs.files').find({}).toArray(function (err, files) {
var Files = files;
for (var i = 0; i < Files.length; i++) {
getFileById(Files[i]._id, function (err, img) {
if (err) {
callback(err, null);
}
else images.push(img);
})
}
});
console.log(images);
}
结果是一个 [] 数组。我犯了什么错误?
编辑:
function getFileById(id, callback) {
gfs.createReadStream({_id: id},
function (err, readStream) {
if (err) callback(err, null);
else {
if (readStream) {
var data = [];
readStream.on('data', function (chunk) {
data.push(chunk);
});
readStream.on('end', function () {
data = Buffer.concat(data);
var img = 'data:image/png;base64,' + Buffer(data).toString('base64');
setTimeout(function () {
callback(null, img);
}, 2000);
})
}
}
});
}
function getAll(callback) {
var images = [];
db.collection('fs.files').find({}).toArray(function (err, files) {
var Files = files;
for (var i = 0; i < Files.length; i++) {
getFileById(Files[i]._id, function (err, img) {
if (err) {
callback(err, null);
}
else images.push(img);
})
}
});
console.log(images);
}
【问题讨论】:
-
基本错误是
console.log()在异步函数的回调运行之前被执行。这里没有告诉它等待。这两个参考问题向您展示了如何处理“回调内部”的结果或以其他方式处理“等待”异步响应。 -
但为什么在我的简化示例中一切顺利?我不明白我的简化示例和实际问题之间的区别。
-
因为你只是在传递值。实际上没有什么需要“等待”I/O。当您花时间阅读现有材料时,实际上已经解释了所有“为什么”。
-
我阅读了您提到的帖子,但我的问题不是那个。当我在 for 循环中记录数组时,一切正常。
-
那你就不能仔细阅读了。这是异步调用的一个非常基本的原则。如果您还没有阅读过这样的示例,那么将您自己的内部函数示例用
setTimeout()包装起来,这实际上将模拟 I/O 等待。那你可能就明白了。
标签: javascript mongodb gridfs