1

Hi fellow Javascript/Node.js-Developer,

I'm running into the good old problem with asynchronous Javascript giving me only the last item of an array (as seen HERE and HERE). Unfortunately neither of the provided solutions worked for me.

I'm running on Node version 0.10.25. I compiled a minimal (not) working example:

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);
}

Expected output:

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

Actuall output:

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

I'm totally stumped. Hopefully someone

3 Answers 3

4

In this code:

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

When you set params.table, every iteration of the foreach function is updating params.table with the next table.

When you call your function below with a timeout of 1000ms, the foreach loop will immediately continue since the timeout is asynchronous, setting params.table to the next table. This will continue until the end of the foreach loop, where params.table is set to the last value in the array.

So when the callbacks of all your timeouts occur, the foreach function will already have completed, and all of your callbacks will print the same value.

Sign up to request clarification or add additional context in comments.

Comments

0

You are reusing the same params object for every function call. So they all see the last update to it.

Simple fix - make a new params object for each function call

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

Even better, as you don't use params outside of the forEach scope, move it in there.

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

And then as you only every set one property of params, just use it directly.

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

4 Comments

Could you kindly explain further why binding "params" wasn't working but binding "table" did the trick? Was it "just" because of the scope?
Because you bound the same object to every function, which you then changed. Each table object is a different one, and you do not change them before the async functions are run.
In short: binding (and any other closure capture) takes a reference, not a copy.
N.B. any of the examples in my answer would also work.
0

Bring your params variable inside the scope of your 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)();
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.