【问题标题】:local variable and callback functions in javascript [duplicate]javascript中的局部变量和回调函数[重复]
【发布时间】: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


【解决方案1】:

如果将console.log("inside") 放在forloop 中会怎样?我想你的console.log(images)

在循环开始之前渲染

【讨论】:

  • 我知道。正如你所说,它只有在我把它放在 for 循环中时才有效。但我不明白我的简化示例和我的实际问题之间有什么区别。它们看起来一样
  • 这是nodejs吗?我想你可以在这里阅读更多内容:exploringjs.com/es6/ch_promises.html
  • 是的,这是 nodeJS。我已经更新了我的代码以向您展示更多细节。有什么问题?
猜你喜欢
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-16
  • 2016-12-27
相关资源
最近更新 更多