我的网站允许用户翻译文件。我想添加一个故障保护,以防用户决定卸载网页(无论是重新加载、导航离开还是关闭选项卡)。我的后端是 django 加 celery[redis]。目前,在用户开始翻译任务后,我的前端每 5 秒轮询一次后端,以查看任务是否仍在运行。下面是对应的JS供参考:
function pollTaskStatus(taskId) {
currentTaskId = taskId;
console.log(currentTaskId)
pollInterval = setInterval(() => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status == 200) {
const response = JSON.parse(xhr.responseText);
if (response.status === 'completed') {
console.log('sent');
showTranslationComplete(response);
clearInterval(pollInterval); // Stop polling once completed
isTranslating = false; // Set to false when translation is complete
}
} else {
showError('An error occurred.');
clearInterval(pollInterval); // Stop polling on error
isTranslating = false; // Set to false on errors
}
};
xhr.onerror = function() {
showError('Connection error. Please check your network connection and try again.');
clearInterval(pollInterval); // Stop polling on network error
isTranslating = false; // Set to false on network error
};
xhr.open('GET', `/translate/poll_task_status/${taskId}/`, true);
xhr.send();
}, 5000); // Poll every 5 seconds
}
我知道在卸载事件期间/之后运行函数是不可靠的,所以我避免了这种情况。任何建议表示赞赏。
尝试一下并检查它是否有效?如果需要的话进行一些修改。
window.addEventListener('beforeunload', function (e) {
if (isTranslating) {
// Show the confirmation prompt
const confirmationMessage = 'Translation in progress. Are you sure you want to leave?';
e.preventDefault();
e.returnValue = confirmationMessage;
// The return value is needed for the browser to show the confirmation prompt
return confirmationMessage;
}
});
window.addEventListener('unload', function (e) {
if (isTranslating) {
// If the user confirmed navigation, stop the task
stopTranslation();
}
});
function stopTranslation() {
if (isTranslating && currentTaskId) {
// Cancel the polling
clearInterval(pollInterval);
// Create an XMLHttpRequest object
const xhr = new XMLHttpRequest();
// Set up the onload event handler
xhr.onload = function() {
if (xhr.status === 200) {
try {
const response = JSON.parse(xhr.responseText);
if (response.status === 'stopped') {
console.log('Translation stopped successfully');
isTranslating = false;
currentTaskId = null;
showTranslationStopped(); // Update UI to reflect the stopped state
} else {
console.error('Unexpected response:', response);
}
} catch (e) {
console.error('Error parsing response JSON:', e);
}
} else {
console.error('Failed to stop translation. Status:', xhr.status);
}
};
// Set up the onerror event handler
xhr.onerror = function() {
console.error('Connection error while trying to stop translation');
};
// Open a POST request to the stop_task endpoint
xhr.open('POST', `/translate/stop_task/${currentTaskId}/`, true);
// Set the appropriate headers (CSRF token for Django)
xhr.setRequestHeader('X-CSRFToken', getCsrfToken());
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// Send the request
xhr.send();
}
}