Frage

The title may be a bit weir, but I don't really know how else to call it. My problem is as follows: I've built an API call which I'm repeatedly calling (every 5 seonds) with this javascript code in my html:

$(document).ready(function(){
    var openTicketRequests = [];
    function getOpenTickets() {
        // Abort all pending openTicketRequests
        for(var i=0; i<openTicketRequests.length; i++) {
            openTicketRequests[i].abort();
        }
        openTicketRequests.push(
            $.ajax({
                type: "GET",
                url: "ticket/get_open",
                dataType: "json",
                success: function(data) {
                    $(".open_tickets").empty(); // Empty the list of open tickets.
                    for (var i=0; i<data.length; i++) {
                        $(".open_tickets").append(data[i].id + "<br/>");
                    }
                }
            }));
        setTimeout(getOpenTickets, 5000);
    }
});

This works fine. Sometimes I call it from a different place in the javascript so that it is run instantly. The problem with that is that it then updates every 2.5 seconds. If I call it again it then runs 3 times per 5 seconds, etc. etc. After a while of running that page, this call is being made about 20 times per 5 seconds instead of once per 5 seconds.

For this reason I added the openTicketRequests array which I loop over to abort the existing pending calls, but this obviously doesn't work very well.

So my question: what am I doing wrong? How can I abort all pending requests so that it is only run once every 5 seconds? All tips are welcome!

War es hilfreich?

Lösung

If you want the code to run every 5 seconds and an ad hoc call to the code should reset the 5 second interval, then you need to capture the return of setTimeout and clear it with clearTimeout[MDN] within getOpenTickets:

$(document).ready(function(){
    var openTicketRequests = [];
    var timeoutID = null;
    function getOpenTickets() {
        // First clear the timer.
        clearTimeout(timeoutID);

        // Abort all pending openTicketRequests
        for(var i=0; i<openTicketRequests.length; i++) {
            openTicketRequests[i].abort();
        }
        openTicketRequests.push(
            $.ajax({
                type: "GET",
                url: "ticket/get_open",
                dataType: "json",
                success: function(data) {
                    $(".open_tickets").empty(); // Empty the list of open tickets.
                    for (var i=0; i<data.length; i++) {
                        $(".open_tickets").append(data[i].id + "<br/>");
                    }
                }
            }));
        timeoutID = setTimeout(getOpenTickets, 5000);
    }
});

If you want the code to run every 5 seconds regardless of whether you've executed the code in an ad hoc fashion, I would separate the code that creates the regular call from the call itself and use setInterval[MDN] instead of setTimeout:

$(document).ready(function(){
    var openTicketRequests = [];
    function getOpenTickets() {
        // Abort all pending openTicketRequests
        for(var i=0; i<openTicketRequests.length; i++) {
            openTicketRequests[i].abort();
        }
        openTicketRequests.push(
            $.ajax({
                type: "GET",
                url: "ticket/get_open",
                dataType: "json",
                success: function(data) {
                    $(".open_tickets").empty(); // Empty the list of open tickets.
                    for (var i=0; i<data.length; i++) {
                        $(".open_tickets").append(data[i].id + "<br/>");
                    }
                }
            }));
    }

    
    setInterval(getOpenTickets, 5000);
});

Now, you can call getOpenTickets ad hoc whenever you want, but it's not going to compound the regular call.


Reference

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top