Why does my XMLHttpRequest cancel my background task before reloading the page
I'm trying to send a XMLHttpRequest to my backend if a user chooses to reload the webpage while a task is running on the backend. It is to function like this:
- The user starts the task(translation).
- If the user decides to reload the page or navigate away they should get an alert that the task will stop if they navigate away. If they still choose to navigate away the request is sent to a
stop_task
view on the backend.
However, currently if the user starts to navigate away or reloads the task is terminated once the alert shows instead of after the user confirms that they still want to reload/navigate away.
Here is my code JS:
wwindow.addEventListener('beforeunload', function (e) {
if (isTranslating) {
stopTranslation();
e.preventDefault();
e.returnValue = '';
return 'Translation in progress. Are you sure you want to leave?';
}
});
function stopTranslaion() {
if (isTranslating && currentTaskId) {
// Cancel the polling
console.log(currentTaskId)
clearInterval(pollInterval);
// Send a request to the server to stop the task
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status == 200) {
const response = JSON.parse(xhr.responseText);
if (response.status === 'stopped') {
console.log('Translation stopped');
isTranslating = false;
currentTaskId = null;
// Update UI to reflect stopped state
showTranslationStopped();
}
} else {
console.error('Failed to stop translation');
}
};
xhr.onerror = function() {
console.error('Connection error while trying to stop translation');
};
xhr.open('POST', `/translate/stop_task/${currentTaskId}/`, true);
xhr.setRequestHeader('X-CSRFToken', getCsrfToken());
xhr.send();
}
}
function showTranslationStopped() {
// Update UI to show that translation has been stopped
translatingFileField.style.display = 'none';
const stoppedMessage = document.createElement('div');
stoppedMessage.textContent = 'Translation has been stopped.';
form.appendChild(stoppedMessage);
}
views.py:
@csrf_protect
def stop_task(request, task_id):
if request.method == 'POST':
try:
# Revoke the Celery task
app.control.revoke(task_id, terminate=True)
return JsonResponse({'status': 'stopped'})
except Exception as e:
return JsonResponse({'status': 'error', 'message': str(e)}, status=500)
return JsonResponse({'status': 'error', 'message': 'Invalid request method'}, status=400)
I would prefer for it to function as detailed in steps 1 and 2. My tasks are handled using Celery with redis