【问题标题】:Javascript & promises with Q - closure problems in promisesJavascript & Promise with Q - Promise 中的闭包问题
【发布时间】:2013-12-16 04:24:02
【问题描述】:

我正在使用 Node.js 和 Q 编写服务器端异步代码。我是 Promise 的新手(而且我通常是异步编程的新手),而且我遇到了一些问题,我无法通过盯着 Q 文档来解决。这是我的代码(它是咖啡脚本 - 如果您想查看 javascript,请告诉我):

templates = {}
promises = []
for type in ['html', 'text']
    promises.push Q.nfcall(fs.readFile
        , "./email_templates/#{type}.ejs"
        , 'utf8'
        ).then (data)->
            # the problem is right here - by the time
            # this function is called, we are done
            # iterating through the loop, and the value 
            # of type is incorrect
            templates[type] = data
Q.all(promises).then(()->
    console.log 'sending email...'
    # send an e-mail here...
).done ()->
    # etc

希望我的 cmets 解释了这个问题。我想遍历类型列表,然后为每种类型运行一系列承诺,但问题是 type 的值正在被更改超出承诺范围。我意识到,对于这么短的列表,我可以展开循环,但这不是一个可持续的解决方案。如何确保每个 Promise 看到不同但本地正确的 type 值?

【问题讨论】:

    标签: javascript node.js coffeescript promise q


    【解决方案1】:

    您必须将您的数据赋值闭包封装在另一个闭包中,以便在执行内部闭包之前保留类型的值。

    更多详情:http://www.mennovanslooten.nl/blog/post/62

    【讨论】:

    • 谢谢。虽然我没有完全复制这个解决方案,但这篇博文中的解释帮助我创建了一个修复程序。
    【解决方案2】:

    我不知道 CoffeeScript,但这应该可以在 JS 中使用:

    var promises = [];
    var templates = {};
    var ref = ['html', 'text'];
    
    for (var i = 0, len = ref.length; i < len; i++) {
        var type = ref[i];
    
        promises.push(Q.nfcall(fs.readFile, "./email_templates/" + type + ".ejs", 'utf8').then((function (type) {
            return function (data) {
                return templates[type] = data;
            };
        }(type))));
    }
    
    Q.all(promises).then(function() {
        return console.log('sending email...');
        // ...
    }).done(function() {
        // ...
    });
    

    编辑:CoffeeScript 翻译:

    templates = {}
    promises = []
    for type in ['html', 'text']
        promises.push Q.nfcall(fs.readFile
            , "./email_templates/#{type}.ejs"
            , 'utf8'
            ).then do (type)->
                (data)->
                     templates[type] = data
    Q.all(promises).then(()->
        console.log 'sending email...'
    ).done ()->
        console.log '...'
    

    重要的部分是:

    ).then do (type)->
        (data)->
            templates[type] = data
    

    【讨论】:

    • @MattBall 我有一个额外的闭包(参见立即调用的函数表达式)。
    • 谢谢,约翰。我相信我明白这里发生了什么。但是,我接受了另一个答案,因为它提供了问题解释的链接,这比快速修复更有帮助。
    • @jayhendren 没问题。我不在乎你接受谁,只要你原来的问题解决了!
    猜你喜欢
    • 2015-10-21
    • 1970-01-01
    • 2016-08-17
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    相关资源
    最近更新 更多