0

So I'm trying to build a web application that will ping a device's registers for stored data every 30 seconds.

enter image description here

as you can see each device can have multiple registers. When a user creates a new device I iterate all the newly created register id's that I return from my ajax post(generated DB id's) and then start an interval timer making an ajax call every 30 seconds to a method that will ping my device and get the data for the specific register.

The problem I'm running into is that every time the interval runs my ajax call, it's reusing the last register id to fetch data instead of running a fetch on each individual register. Ex. my 2 rows have an id of 22 and 23. Everytime my interval function is called it will use id 23 and make the ajax call instead of calling 22 then 23. Is this because I'm using a for loop when instantiating a new interval?

Here is how I try to handle my setInterval:

        var registers = result.register_ids;
        for (var i = 0; i < registers.length; ++i) {
            debugger;
            var interval = setInterval(function () { fetchRegisterValues(registers[i], result.modbus_id) }, 30000);
            register_ping_threads[registers[i]] = interval;
        }

Here is my ajax call to read the specified register:

function fetchRegisterValues(register_id, modbus_id) {//id always ends up being 23
    debugger;
    $.ajax({
        type: "POST",
        url: "/fetch_mdata",
        data: {
            'csrfmiddlewaretoken': token,
            'register_id': register_id, //use to read the register range
            'modbus_id': modbus_id //used to get device connectiong settings
        },
        contentType: "application/x-www-form-urlencoded",
        dataType: 'json',
        success: function (result) {
            debugger;

            $('[data-register="' + register_id + '"]').find('[data-value=""]').text(result.value);
        },
        error: function (data) {
            debugger;
            $('#loading-icon').hide()

            $('#ping_error').addClass('alert alert-danger');
            $('#ping_error strong').append('Problem contacting server..');
        }
    });
}
john
  • 3,949
  • 7
  • 34
  • 56

1 Answers1

1

This is a very common mistake in JavaScript. Remember that i is in a scope of a function, not the scope of the loop, so all your fetchRegisterValues will reuse the same value of i. To fix it, create a new scope:

    for (var i = 0; i < registers.length; ++i) {
        debugger;
        var interval = setInterval((function (i) { return function() { fetchRegisterValues(registers[i], result.modbus_id) } })(i), 30000);
        register_ping_threads[registers[i]] = interval;
    }
Ishamael
  • 12,583
  • 4
  • 34
  • 52