I'm trying to dynamically create PDFs on a webserver using PHP/wkhtmltopdf, which involves sending the PDF-generation process to the background in order to prevent the page timing out.
To check whether the job has completed successfully, I've used Javascript (which I suck at) and more specifically jQuery/AJAX to continuously query the server looking to see if wkhtmltopdf's process has ended. If its still running, the PHP script returns nothing and simply exits. If the process has ended successfully, a html link to the PDF is generated and then dumped into a <div></div>.
All the server side code works flawlessly however I'm stuck on the Javascript component. The code below kinda works but instead of the timer stopping after a PDF has been generated, it continues to query the server. How do I get it to stop?
$('#pdfmodal').on('shown', function () {
pdf(); // fire PDF generation process function
(function worker() {
$.ajax({
url: 'pdfpidcheck.php',
success: function(data) {
if(data == ''){
// Schedule the next request if nothing returned (i.e. still running)
setTimeout(worker, 5000);
} else {
// dump link to pdf
$('.pdfmodal').html(data);
}
}
});
})();
})
1 Answer 1
To stop a timer, you just remember the returned value from setTimeout() and call clearTimeout() on it.
var id = setTimeout(fn, 5000);
// then some time later
clearTimeout(id);
In the code you've shown us, this should not be an issue unless you are calling worker() from some other place than what you show us or unless the .on() handler gets called a second time while a PDF is being created. Your current code doesn't look like it knows how to handler two PDFs being created at the same time or a second even triggered while the first one is still processing.
You could protect against multiple timers running like this:
$('#pdfmodal').on('shown', function () {
var modal = $(this);
pdf(); // fire PDF generation process function
(function worker() {
$.ajax({
url: 'pdfpidcheck.php',
success: function(data) {
var timer = modal.data(timer);
if(data == ''){
// make sure we never have more than one timer running
if (timer) clearTimeout(timer);
// Schedule the next request if nothing returned
// (i.e. server process still running)
timer = setTimeout(worker, 5000);
// save timer for later use
modal.data("timer", timer);
} else {
// clean up timer data
if (timer) clearTimeout(timer);
modal.removeData("timer");
// dump link to pdf
$('.pdfmodal').html(data);
}
}
});
})();
})
pdf()which inturn invokes it again with timeout and it goes on and on.