2016-04-25 6 views
0

Angenommen, ich habe die folgende Abfrage-Funktion:Polling Ajax-Funktion wird von über Call-Stack

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); 
} 

Als ich es aufrufen, den Erfolg Rückruf nie aufgerufen wird, oder es könnte sein, aber mein console.logs nie erscheinen. Statt nach einer Weile bekomme ich

Uncaught RangeError: Maximum call stack size exceeded 

Also meine Funktion rekursiv ausgeführt wird, sondern in der Art und Weise, dass ich es will. Ich würde zumindest hoffen, das Konsolenprotokoll vor dem Start meiner rekursiven Aufrufe in der Konsole auszudrucken, tut es aber nicht. Ich habe bestätigt, dass mein Backend-Endpunkt korrekt funktioniert und json zurückgibt, also vermute ich, dass etwas in meinem JavaScript-Code fehlt. Hat jemand eine Idee?

+0

Ich würde auch einen Fehlerhandler hinzufügen und 'console.log' was kommt da rein? Haben Sie im Netzwerk-Panel bestätigt, dass Sie eine Antwort von 200 erhalten? – winhowes

+0

Nicht sicher, ob dies hilft, aber Sie möglicherweise auf das Problem mit console.log erwähnt hier: http://stackoverflow.com/questions/8395718/javascript-funky-array-mishap. – Blue

+0

Es gibt keine Rekursion in Ihrem Code im Sinne von geschachtelten Funktionsaufrufen. 'setTimeout' ist asynchron und auch' $ .ajax'. Keine 'pollingFunc'-Ausführung hat einen weiteren' pollingFunc' im Aufruf-Stack. Es läuft noch etwas anderes, das wird in Ihrer Frage nicht angezeigt. – Igor

Antwort

1

Ich bin nicht gut in js, aber ich hatte Probleme mit setTimeout. Nach w3school:

Anzeige ein Warnfeld nach 3 Sekunden (3000 Millisekunden):

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

Also ich denke, Ihr Code 5 secondes wartet vor Ihrem Server aufrufen, und dann Sie nennen es jedes Mal und sofort, wenn Sie die Antwort bekommen.

=> Um Ihr Problem zu beheben, setzen Sie die setTimeout innerhalb die Erfolgsfunktion.

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, nicht diese Art von Problem zu reproduzieren, würde ich separat diese Funktion auch erklären, wie empfohlen, durch JQuery documentation.

+0

Ja, ich wollte meinen Kuchen haben und auch essen, indem ich eine wiederverwendbare Abfragefunktion habe, die außerhalb des Erfolgsrückrufs definiert ist, damit ich sie wiederverwenden kann. Wenn sich herausstellt, dass dies nicht möglich ist, werde ich diese Antwort akzeptieren. – theamateurdataanalyst

+0

Ich bearbeitete meine Antwort mit einer Anpassung Ihres Codes, der immer noch eine wiederverwendbare Funktion ist, hoffe, es wird helfen! – vtellier

+1

"Sie rufen es jedes Mal und sofort" - rufen Sie was sofort? Er ruft 'pollingFunc' auf, wodurch nur ein' setTimeout' in die Warteschlange gestellt und beendet wird. – Igor