Perhaps you get confused because the loop never actually does stop. And it's not a loop, it's recursion. It's recursion with no end condition: poll will always call itself.
Load the page using Chrome. Rclick anywhere in the page, click ”inspect element”, then click ”network” in the new window. Click the button that initiates the entire process. As you can see, it never stops sending ajax requests. (other browsers have similar tools - use whatever tools you find suitable. but do use them)
You should also change some other things. First off, you start by performing an ajax request, and then you proceed to register an event handler for ajaxStop (which will be called whenever an ajax request finishes if there are no other ajax requests in progress. If the first ajax requests finishes quickly enough, you will not have registered the ajaxStop handler in time, and it will not fire (the first time). Thus, the order in which these things are done ought to be changed.
But more importantly, you register a new identical anonymous function for each new ajax request which means that
- after the first ajax request is done, one anonymous function is called on ajaxStop
- after the second ajax request is done, two anonymous functions are called on ajaxStop
…
- after the 100th ajax request is done, 100 anonymous functions are called on ajaxStop
I don't believe that these identical functions actually have to be separate functions, but I'd guess that they will be separate functions in current javascript implementations.
I recommend changing the logic by refactoring the outermost doEverythingFunction (the document ready handler) so that
- it registers one event handler for the button click called something like sendEmail, but nothing else
- you define sendEmail outside of the document ready handler
- sendEmail only performs the first ajax request (to send email)
- you break out everything dealing with polling for progress into a function called something like poll
- define poll outside the document ready function
- then go back to the first ajax request (in sendEmail), and on success...
- call function poll
- poll now only performs an ajax request
- which on success...
- checks if job is not done...
- and then calls itself (using setTimeout - You only need the timeout when recalling poll)
- if job is done… well, then the job is done. no need for poll to call itself again.
Please note that the call to setTimeout now will only specify an already defined function to call, rather than defining a new identical function every time. If you only call setTimeout once, then you may just as well define an anonymous function in place. But otherwise you are better off defining the function once and calling it many times. This is similar to how
function foo() { /* function body */ }
foo();
foo();
is preferable to
(function () { /* function body */ }());
(function () { /* function body */ }());