ajax 요청을 간편하게 정보
ajax 요청을 간편하게본문
매번 ajax 요청 코드를 작성하는 게 귀찮아서 함수로 만들어서 사용 중입니다.
필요하다면 상황에 맞게 수정하셔서 사용하시면 되지 싶습니다.
const App = window.App || {};
App.callbacks = {};
document.addEventListener('DOMContentLoaded', function () {
addProgressStyles();
addProgressElement();
document.addEventListener('click', handleButtonClick);
});
function addProgressStyles() {
const style = document.createElement('style');
style.textContent = `
#progress { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 9999; overflow: hidden; background: #000; opacity: .1; }
#progress:after { content: ""; position: fixed; top: calc(50% - 30px); left: calc(50% - 30px); border: 6px solid #60718b; border-top-color: #fff; border-bottom-color: #fff; border-radius: 50%; width: 60px; height: 60px; animation: animate-progress 1s linear infinite; }
@keyframes animate-progress {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`;
document.head.appendChild(style);
}
function addProgressElement() {
const progress = document.createElement('div');
progress.id = 'progress';
document.body.appendChild(progress);
}
function handleButtonClick(event) {
if (event.target.classList.contains('btn-form-submit-ajax')) {
handleAjaxFormSubmit(event.target);
}
}
// 상황에 맞게 수정하거나 삭제
const API_BASE_URL = window.API_FULL_BASE_URL || '/api/v1';
let cachedCsrfToken = null;
// CSRF 토큰을 가져오는 함수 //상황에 맞게 수정하거나 삭제
async function getCsrfToken() {
if (cachedCsrfToken) return cachedCsrfToken;
try {
const response = await fetch(`${API_BASE_URL}/token/getUserCsrfToken`);
if (!response.ok) throw new Error('Failed to fetch CSRF token');
const data = await response.json();
if (!data.token) throw new Error('CSRF token not found in response');
cachedCsrfToken = data.token;
return cachedCsrfToken;
} catch (error) {
console.error('Error fetching CSRF token:', error);
throw error;
}
}
// CSRF 토큰을 초기화하는 함수
function resetCsrfToken() {
cachedCsrfToken = null;
}
// AJAX 요청을 보내는 함수
async function sendAjaxRequest(method, url, data, isFormData = false, isLoading = false, retryCount = 0) {
try {
// CSRF 토큰 관련 함수 및 아래 부분에 상황에 맞게 수정하거나 삭제
const csrfToken = await getCsrfToken();
const options = {
method,
headers: {
'X-CSRF-Token': csrfToken
}
};
if (method.toUpperCase() !== 'GET') {
if (isFormData && data instanceof FormData) {
options.body = data;
} else if (!isFormData) {
options.headers['Content-Type'] = 'application/json';
options.body = JSON.stringify(data);
} else {
throw new Error('Invalid data type for isFormData=true');
}
} else if (data) {
url += (url.includes('?') ? '&' : '?') + new URLSearchParams(data).toString();
}
if (isLoading) toggleProgress(true);
const response = await fetch(url, options);
const responseData = await response.json();
if (isLoading) toggleProgress(false);
if (!response.ok) {
if (response.status === 419 && retryCount < 3) { // CSRF 토큰 만료 시 반환하는 상태 코드, 최대 3번 재시도
//console.log('CSRF 토큰이 만료되어 새로운 토큰을 요청합니다.');
resetCsrfToken();
// 재귀적으로 동일한 요청을 다시 시도
return sendAjaxRequest(method, url, data, isFormData, isLoading, retryCount + 1);
}
throw new Error(responseData.error || 'Request failed');
}
return responseData;
} catch (error) {
handleError(error);
return Promise.reject(error); // 호출한 곳으로 에러 전달
}
}
// AJAX 폼 제출 처리 함수
async function handleAjaxFormSubmit(button) {
const form = button.closest('form');
const url = button.getAttribute('data-target');
const beforeSubmitFunctionName = button.getAttribute('data-beforesubmit');
const callbackFunctionName = button.getAttribute('data-callback');
const loading = button.getAttribute('data-loading') === 'true';
// 폼 전송 전 함수 실행
if (beforeSubmitFunctionName) {
const shouldProceed = await executeCallback(beforeSubmitFunctionName);
if (!shouldProceed) {
return; // beforeSubmit 함수가 false를 반환하면 폼 전송 중단
}
}
// TinyMCE 에디터 내용 저장 - 타에디터 사용 시 해당 에디터에 맞게 수정.
document.querySelectorAll('.editor-form').forEach(editor => {
if (tinymce.get(editor.id)) {
tinymce.get(editor.id).save();
}
});
if (!validateForm(form)) return; // 폼을 체크하는 함수, 삭제 후 사용
button.disabled = true;
try {
const formData = new FormData(form);
const data = await sendAjaxRequest('POST', url, formData, true, loading);
if (data.result === "success") {
if (callbackFunctionName) {
executeCallback(callbackFunctionName, data);
}
} else {
alert('오류: ' + (data.message || '알 수 없는 오류가 발생했습니다.'));
}
} catch (error) {
handleError(error);
} finally {
button.disabled = false;
}
}
async function sendCustomAjaxRequest(method, url, data, loading = false, callbackFunctionName = null) {
try {
const responseData = await sendAjaxRequest(method, url, data, false, loading);
if (callbackFunctionName) {
executeCallback(callbackFunctionName, responseData);
}
return responseData;
} catch (error) {
handleError(error);
return Promise.reject(error);
}
}
// 콜백 함수 실행
function executeCallback(callbackFunctionName, data) {
if (typeof App.callbacks[callbackFunctionName] === 'function') {
App.callbacks[callbackFunctionName](data);
}
}
// 에러 핸들러
function handleError(error) {
const errorMessage = error.message || '알 수 없는 오류가 발생했습니다.';
if (errorMessage.includes('CSRF 토큰이 만료되었습니다')) {
console.error(errorMessage);
} else {
console.error('Error: ' + errorMessage);
}
}
// 프로그레스 표시 토글 함수
function toggleProgress(show = true) {
const progress = document.getElementById('progress');
if (progress) progress.style.display = show ? 'block' : 'none';
}
function prettyPrintJson(data) {
console.log(JSON.stringify(data, null, 2));
}
// 콜백 함수 등록
App.registerCallback = function(name, callback) {
if (typeof callback === 'function') {
App.callbacks[name] = callback;
} else {
//console.error(`Invalid callback function for ${name}`);
}
};
## 폼 전송 시
<form name="frm" id="frm" enctype="multipart/form-data">
<!-- form html --->
<button type="button" value="확인" data-target="url경로" data-beforesubmit="beforeSubmit" data-callback="fnCallback">확인</button>
</form>
## 폼 이외 전송 시
<button type="button" value="확인" onclick="submitAjax();">확인</button>
<script>
function submitAjax() {
var data = {data1:data1, data2:data2}; //전송할 데이터
var url = '/ajax.php'; //ajax 파일 경로
try {
const result = await sendCustomAjaxRequest('POST', url, data, true, 'customFnCallback');
}
catch (error) {
alert('순위 검색에 실패했습니다: ' + (error.message || '알 수 없는 오류'));
}
}
// ajax 전송 전 또는 전송 후 실행할 함수 , 물론 함수명은 샘플임.
App.registerCallback('beforeSubmit', function(data) {
console.log(data);
});
App.registerCallback('fnCallback', function(data) {
console.log(data);
});
App.registerCallback('customFnCallback', function(data) {
console.log(data);
});
</script>
!-->9
댓글 5개

감사합니다 ^^
감사합니다.
함수를 자체적으로 만드는 분을 보면 대단하다고 생각합니다.

오호 css 까지 동적으로 생성하셨네요. 추천

감사합니다.

감사합니다