Javascript Node.js仅使用数组中的最后一项

Javascript Node.js仅使用数组中的最后一项,javascript,arrays,node.js,asynchronous,Javascript,Arrays,Node.js,Asynchronous,大家好,Javascript/Node.js-Developer同事 我遇到了一个很好的老问题,异步Javascript只提供了数组的最后一项,如图所示。不幸的是,提供的两种解决方案对我都不起作用 我运行的是节点版本0.10.25。我编译了一个最小的不起作用的示例: var neededTables = [{ name: "ipfix_exporters", },{ name: "ipfix_messages", }

大家好,Javascript/Node.js-Developer同事

我遇到了一个很好的老问题,异步Javascript只提供了数组的最后一项,如图所示。不幸的是,提供的两种解决方案对我都不起作用

我运行的是节点版本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);
}
预期产出:

实际输出:

我完全被难住了。希望这段代码中有人

neededTables.forEach(function(table) {
        params.table = table;
        console.log("Checking table: " + params.table.name);
        checkForTable.bind(null, params)();
});
设置params.table时,foreach函数的每次迭代都会使用下一个表更新params.table

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

因此,当所有超时的回调发生时,foreach函数将已经完成,并且所有回调将打印相同的值。

在此代码中:

neededTables.forEach(function(table) {
        params.table = table;
        console.log("Checking table: " + params.table.name);
        checkForTable.bind(null, params)();
});
设置params.table时,foreach函数的每次迭代都会使用下一个表更新params.table

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


因此,当所有超时发生回调时,foreach函数将已经完成,并且所有回调将打印相同的值。

将您的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)();
});

将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)();
});
您正在为每个函数调用重用相同的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对象。所以他们都看到了最后的更新

简单修复-为每个函数调用创建一个新的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)();
});

请您进一步解释为什么绑定参数不起作用,而绑定表起作用?这仅仅是因为作用域吗?因为您将同一对象绑定到每个函数,然后对其进行了更改。每个表对象都是不同的,在异步函数运行之前您不会更改它们。简言之:绑定和任何其他闭包捕获都是引用,而不是副本。注意。我的答案中的任何一个例子都可以。您能进一步解释为什么绑定参数不起作用,而绑定表起了作用吗?这仅仅是因为作用域吗?因为您将同一对象绑定到每个函数,然后对其进行了更改。每个表对象都是不同的,在异步函数运行之前您不会更改它们。简言之:绑定和任何其他闭包捕获都是引用,而不是副本。注意。我的答案中的任何一个例子都是有效的。