0

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

Lumpy
  • 105
  • 1
  • 3
  • 13
  • 3
    You're immediately scheduling it for 30 seconds from now. If you want it to run immediately, don't schedule it for 30 seconds from now with `setTimeout`...? Maybe what you want to do is have `poll` immediately make the call, and then delay *future* calls to `poll` by 30 seconds? – apsillers Mar 28 '17 at 14:40
  • Also, why do you want to trigger it right after your page just got refreshed? - I assume you don't trigger it by a click event... – Jeroen Bellemans Mar 28 '17 at 14:42
  • @apsillers So instead of setTimeout to poll immediately and how about how to set up future calls? – Lumpy Mar 28 '17 at 15:34
  • @JeroenBellemans The page loads and I want to detect what to display control wise, meaning if buttons or divs needs to be enabled or disabled. So on page load I want it to check and then keep checking until a status has changed based on the ajax call's response. – Lumpy Mar 28 '17 at 15:36
  • i mean... that's what setTimeout does. it waits. – Kevin B Mar 28 '17 at 18:54
  • @Kevin B As stated before, i want to kick it off immediately then start the timer to start waiting. I guess I would need to figure to manually kick it off and then start the timer which would require more code then expected. – Lumpy Mar 29 '17 at 18:39
  • Right. so... do that. – Kevin B Mar 29 '17 at 18:40
  • @Kevin B Look I'm trying to learn here, no need to be so condescending and sarcastic about things. – Lumpy Mar 30 '17 at 15:05
  • @Lumpy you already have two answers that do what you ask. – Kevin B Mar 30 '17 at 15:06
  • @Kevin B I'm the person asking the question so if the answers did not work for me in my case, then who are you to tell me if the answer fits my needs? I did mark Malvolio answer as the correct answer. Get off your high horse in thinking you can dictate people's actions. This is a community to learn from one another, not push people around. – Lumpy Mar 30 '17 at 15:18

2 Answers2

1

If you are writing some polling function you must send request after previous was complete. The server have to respond to browser after several seconds. In this time server process all other requests. Here is example:

(function poll() {
            console.log('polling called');

            $.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);
                },
                complete: function () {
                    setTimeout(function () {
                        poll()
                    }, 200) //do nothing 200ms
                }
            });
        })();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Alex Slipknot
  • 2,439
  • 1
  • 18
  • 26
  • Looks like running your code snippet, the actual ajax call does not get executed since it does not log out the statements within the success. It only logs the "polling called" statement. – Lumpy Mar 29 '17 at 17:58
  • Of course it's not :) Because server does not exists :) It's just an example to show how to implement long-polling – Alex Slipknot Mar 29 '17 at 18:44
  • What I meant was it did not work when I implemented it in my environment either. Sorry for the confusion. Thanks – Lumpy Mar 30 '17 at 15:00
  • Ah, ok, so what exactly doesn't work? Any error? If request was not successful you can add method to detect what kind of error happened – Alex Slipknot Mar 30 '17 at 15:15
  • I apologize, it was a mistake on my end. The server request had an error and never returned. Your solution is a very valid one and should work in all browsers. – Lumpy Apr 02 '17 at 13:27
0

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.
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144