【问题标题】:Node.js only uses last item in arrayNode.js 仅使用数组中的最后一项
【发布时间】:2014-02-21 00:50:37
【问题描述】:

您好,Javascript/Node.js 开发人员,

我遇到了异步 Javascript 的老问题,只给我数组的最后一项(如 HEREHERE 所示)。不幸的是,提供的解决方案都不适合我。

我在 Node 版本 0.10.25 上运行。我编译了一个最小(非)工作示例:

var neededTables = [{
                name: "ipfix_exporters",
        },{
                name: "ipfix_messages",
}];

var params = {};

console.log('[1] Connected to hana-database');
neededTables.forEach(function(table) {
        params.table = table;
        console.log("Checking table: " + params.table.name);
        checkForTable.bind(null, params)();
});

function checkForTable(thoseParams) {
        setTimeout(
        (function(myParams) { return function(err, rows) {
                if(err) {
                        console.log(err);
                        return;
                }
                console.log("Table '"+myParams.table.name+"' does exist!");
        }})(thoseParams), 1000);
}

预期输出:

[1] Connected to hana-database
Checking table: ipfix_exporters
Checking table: ipfix_messages
Table 'ipfix_exporters' does exist!
Table 'ipfix_messages' does exist!

实际输出:

[1] Connected to hana-database
Checking table: ipfix_exporters
Checking table: ipfix_messages
Table 'ipfix_messages' does exist!
Table 'ipfix_messages' does exist!

我完全被难住了。希望有人

【问题讨论】:

    标签: javascript arrays node.js asynchronous


    【解决方案1】:

    您为每个函数调用重复使用相同的 params 对象。所以他们都看到了它的最后更新。

    简单修复 - 为每个函数调用创建一个新的 params 对象

    neededTables.forEach(function(table) {
        params = {};
        params.table = table;
        console.log("Checking table: " + params.table.name);
        checkForTable.bind(null, params)();
    });
    

    更好的是,因为您不在forEach 范围之外使用params,所以将它移到那里。

    neededTables.forEach(function(table) {
        var params = { table: table };
        console.log("Checking table: " + params.table.name);
        checkForTable.bind(null, params)();
    });
    

    然后因为你只设置params的一个属性,直接使用就行了。

    neededTables.forEach(function(table) {
        console.log("Checking table: " + table.name);
        checkForTable.bind(null, table)();
    });
    

    【讨论】:

    • 您能否进一步解释一下为什么绑定“params”不起作用但绑定“table”却成功了?是因为范围而“只是”吗?
    • 因为您将 same 对象绑定到每个函数,然后您对其进行了更改。每个table 对象都是不同的,在异步函数运行之前不要更改它们。
    • 简而言之:绑定(和任何其他闭包捕获)需要引用,而不是副本。
    • 注:我的回答中的任何例子都可以。
    【解决方案2】:

    将您的 params 变量带入您的 forEach 范围内:

    console.log('[1] Connected to hana-database');
    
    neededTables.forEach(function(table) {
            var params = {};
            params.table = table;
            console.log("Checking table: " + params.table.name);
            checkForTable.bind(null, params)();
    });
    

    【讨论】:

      【解决方案3】:

      在这段代码中:

      neededTables.forEach(function(table) {
              params.table = table;
              console.log("Checking table: " + params.table.name);
              checkForTable.bind(null, params)();
      });
      

      当您设置 params.table 时,foreach 函数的每次迭代都会使用下一个表更新 params.table。

      当您以 1000 毫秒的超时时间调用下面的函数时,foreach 循环将立即继续,因为超时是异步的,将 params.table 设置为下一个表。这将一直持续到 foreach 循环结束,其中 params.table 被设置为数组中的最后一个值。

      所以当你的所有超时回调发生时,foreach 函数已经完成,你所有的回调都将打印相同的值。

      【讨论】:

        猜你喜欢
        • 2023-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-01
        • 2021-02-23
        • 2014-11-11
        • 2011-10-23
        • 1970-01-01
        相关资源
        最近更新 更多