Search code examples
javascriptajaxsettimeoutanonymous-functionpolling

Anonymous javascript polling function does not trigger setTimeout ajax call immediately


I have an anonymous polling function which has a setTimeout to kick off a ajax call every 30 seconds. However, the anonymous function does kick off immediately but for some reason the ajax call does not kick off immediately, but starts only after the 30 seconds. Am I missing something like calling it immediately to trigger right away?

(function poll() {
        console.log('polling called');
        setTimeout(function () {
            $.ajax({
                url: "/server/call",
                type: 'GET',
                dataType: "json", 
                timeout: 30000,
                success: function (data) {
                    var currentdate = new Date();
                    var datetime = "Last Sync: " +                  currentdate.getDate() + "/" + (currentdate.getMonth() + 1) + "/"
                    + currentdate.getFullYear() + " @ "
                    + currentdate.getHours() + ":"
                    + currentdate.getMinutes() + ":"
                    + currentdate.getSeconds();

                    console.log(datetime);
                    console.log('call was successful at: ' + datetime);
                }
            });
        },
        30000);
    })();

The logging just starts off only after 30 seconds and not right away. Thanks


Solution

  • That is not remotely what setTimeout() does. setTimeout() calls its function, once, and only after the given time has expired.

    setInterval() is close to what you want, but even that only calls the function the first time after the interval has expired once.

    What you need is to do this:

    const everyThree = () => 
                $.ajax({
                    url: "/server/call",
                    type: 'GET',
    ...
    everyThree();
    setInterval(everyThree, 3000);
    

    If you don't like using setInterval(), you can do the same thing manually:

    const everyThree = () => {
                setTimeout(everyThree, 3000); 
                $.ajax({
                    url: "/server/call",
                    type: 'GET',
    ...
    everyThree();
    

    If you suspect the AJAX call might run long, you could do the following:

    const everyThree = () => 
                $.ajax({
                    url: "/server/call",
                    type: 'GET',
               ...
               })
               .always(() => setTimeout(everyThree, 3000)); 
    
    everyThree();
    

    This will make the next AJAX call 3 seconds after the previous one has succeeded, failed, or timed-out.

    Edit:

    If you don't have const or => ("fat-arrow") in your environment, your choices are

    1. Make do with var and function. They are inferior in many ways, but universally available.
    2. Use a transpiler like Babel and get all the advantages of a modern language (constants, easy anonymous functions, deconstruction, array-spreading), at the cost of a slight increase in complexity in your operational environment.