0

Suppose I have the following polling function:

function pollingFunc(taskId){
  setTimeout(function() {
    $.ajax({
      url: '/endpoint',
      type: 'POST',
      data: { 'celery_task_id': taskId },
      success: function(response){
        if(response.celery_ready) {
          console.log('CELERY IS READY')
        } else {
          console.log('polling')
          pollingFunc(response.task_id)
        }
      }
    })
  }, 5000);
}

When I invoke it, the success callback is never invoked or it might be, but my console.logs never appear. Instead after a while I get

Uncaught RangeError: Maximum call stack size exceeded

So my function is running recursively, but in the way that I would want it to. I would hope at lease the console log before my recursive calls start would print in the console, but it doesn't. I have confirmed that my backend endpoint is operating correctly and is returning json, so I suspect there is something in my javascript code that I am missing. Anyone have any idea?

theamateurdataanalyst
  • 2,794
  • 4
  • 38
  • 72
  • I would add an error handler as well and `console.log` whatever comes in there? Have you confirmed in the network panel that you're getting a 200 response? – winhowes Apr 25 '16 at 23:14
  • Not sure if this helps but you may be running into the issue with console.log mentioned here: http://stackoverflow.com/questions/8395718/javascript-funky-array-mishap. – Blue Apr 25 '16 at 23:25
  • There is no recursion in your code in the sense of nested function calls. `setTimeout` is asynchronous and so is `$.ajax`. No `pollingFunc` execution has another `pollingFunc` up the call stack. Something else is going on, that is not shown in your question. – Igor Apr 26 '16 at 01:35

1 Answers1

1

I'm not good at js, but I had problems with setTimeout. According to w3school:

Display an alert box after 3 seconds (3000 milliseconds):

setTimeout(function(){ alert("Hello"); }, 3000);

So I think your code is waiting 5 secondes before calling your server, and then you call it each time and immediately when you get the answer.

=> To fix your problem, put the setTimeout inside the success function.

function pollingFunc(taskId){
    $.ajax({
      url: '/endpoint',
      type: 'POST',
      data: { 'celery_task_id': taskId },
      success: function(response){
        if(response.celery_ready) {
          console.log('CELERY IS READY')
        } else {
          console.log('polling')
          setTimeout(function() {
            pollingFunc(response.task_id);
          }, 5000);
        }
      });
  }

By the way, to not reproduce that kind of problem, I would also declare separately that function, as advised by JQuery documentation.

VincentTellier
  • 558
  • 6
  • 16
  • Yeah I wanted to have my cake and eat too by having a reusable polling function that is defined outside of the success callback so I can reuse it. If there turns out to be no way to do this, I'll go ahead and accept this answer. – theamateurdataanalyst Apr 25 '16 at 23:32
  • I edited my answer with an adaptation of your code which is still a reusable function, hope it will help! – VincentTellier Apr 25 '16 at 23:46
  • 1
    "you call it each time and immediately" - call what immediately? He calls `pollingFunc`, which only queues another `setTimeout` and exits. – Igor Apr 26 '16 at 01:43
  • @Igor Yes, you're true. – VincentTellier Apr 26 '16 at 07:07