Skip to content Skip to sidebar Skip to footer

Calling SetTimeout() For All Members In Object - Never Called For 1st Member, And Called For 2nd Member. Why?

I have a 3D array (rather JS object), called outerArray in the SSCCE I am posting here in this question, and it contains inner arrays (rather objects), each of which contains sever

Solution 1:

This is related to the scope of setTimeout, with your current code what happens is that when setTimeout gets executed it reads the last value for innerArray which points to the array of interval 10. There are 2 ways (at least) to solve this:

1) Using immediately invoked function wrapper to create a separate scope for each setTimeout with proper reference to the innerArray variable:

$(document).ready(function() {

    var outerArray = {
        0: {
            0: {
                url: "abc.example.com",
                interval: 7
            },
            1: {
                url: "def.example.com",
                interval: 7
            }
        },

        1: {
            0: {
                url: "ghi.example.com",
                interval: 10
            }
        }
    };




    for (var innerArrayKey in outerArray) {
        var innerArray = outerArray[innerArrayKey];

        (function next(index) {
            console.log("Function loop iteration " + index + " for urls with interval " + innerArray[0]["interval"]); //check
            setTimeout(function(innerArray) {
                return function() {
                    console.log("setTimeout() called for urls with interval " + innerArray[0]["interval"]); //check
                    $.ajax({
                        url: "http://xxx.yyy.xx.yy/testAsynchronousJSRequests/ajax.php",
                        method: "post",
                        data: {
                            innerArray: innerArray
                        },
                        success: function(dataReturned, stringStatus, jqXHR) {
                            console.log("Success for AJAX request for urls with interval " + innerArray[0]["interval"]); //check
                            next(index + 1);
                        },
                        error: function(jqXHR, stringStatus, stringExceptionThrown) {
                            console.log("Error in AJAX request " + innerArray[0]["interval"]); //check
                        }
                    });
                }
            } (innerArray), (innerArray[0]["interval"] * 1000));

        })(0);
    }

});

2) Using ES6 let keyword which creates a separate scope for each iteraion:

$(document).ready(function() {

    var outerArray = {
        0: {
            0: {
                url: "abc.example.com",
                interval: 7
            },
            1: {
                url: "def.example.com",
                interval: 7
            }
        },

        1: {
            0: {
                url: "ghi.example.com",
                interval: 10
            }
        }
    };




    for (var innerArrayKey in outerArray) {
        let innerArray = outerArray[innerArrayKey];

        (function next(index) {
            console.log("Function loop iteration " + index + " for urls with interval " + innerArray[0]["interval"]); //check
            setTimeout(function() {
                console.log("setTimeout() called for urls with interval " + innerArray[0]["interval"]); //check
                $.ajax({
                    url: "http://xxx.yyy.xx.yy/testAsynchronousJSRequests/ajax.php",
                    method: "post",
                    data: {
                        innerArray: innerArray
                    },
                    success: function(dataReturned, stringStatus, jqXHR) {
                        console.log("Success for AJAX request for urls with interval " + innerArray[0]["interval"]); //check
                        next(index + 1);
                    },
                    error: function(jqXHR, stringStatus, stringExceptionThrown) {
                        console.log("Error in AJAX request " + innerArray[0]["interval"]); //check
                    }
                });
            }, (innerArray[0]["interval"] * 1000));

        })(0);
    }

});

You may check this to understand more: JavaScript Closures: setTimeout Inside a For Loop


Post a Comment for "Calling SetTimeout() For All Members In Object - Never Called For 1st Member, And Called For 2nd Member. Why?"