제너레이터 함수를 다루어 보았을까? 만약 그렇다면, async/await이 없던 시절에 개발을 했던 사람일 수 있다.
자 오늘은 옛날 코드 다시보기가 될 수 있을 수 있다.
callBack
자 하나하나씩 보도록 하자. 일단 xmlHttpRequest나 form방식은 건너띄고, 우리에게 친숙한 callback 방식이다.
// callBack 버전
$.ajax({
url: 'https://jsonplaceholder.typicode.com/comments',
dataType: 'json',
success: function(comments) {
// 댓글 목록을 처리합니다.
// ...
// 댓글 목록을 가지고 POST API 호출
const comment = comments[0]; // 첫 번째 댓글 선택
const postData = {
postId: comment.postId,
name: comment.name,
email: comment.email,
body: comment.body,
};
$.ajax({
url: 'https://jsonplaceholder.typicode.com/comments',
method: 'POST',
data: JSON.stringify(postData),
dataType: 'json',
success: function(data) {
console.log('새로운 댓글이 생성되었습니다:', data);
},
error: function(err) {
console.error('댓글 생성에 실패했습니다:', err);
},
});
},
error: function(err) {
console.error('댓글 목록을 가져오는 데 실패했습니다:', err);
},
});
당연하게도, 위의 코드의 문제는.... 저 값의 결과를 가지고 무엇인가 하려면, callBack안에 또 api호출이 들어가게 된다... callBack지옥이라고 들어봤을것이다.
그래도 위의 코드는 그래도.... 뭐... 볼만한 코드긴 할 것이다. 하지만, 검증하는 코드들이나 꽤나 복잡한 하나의 api콜이 추가만 되어도 끔찍한 코드가 될 것이다.
Promise
// Promise 버전
const getComments = () => {
return fetch('https://jsonplaceholder.typicode.com/comments')
.then(response => response.json());
};
const createPost = (postData) => {
return fetch('https://jsonplaceholder.typicode.com/comments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData),
})
.then(response => response.json());
};
getComments()
.then(comments => {
const comment = comments[0]; // 첫 번째 댓글 선택
const postData = {
postId: comment.postId,
name: comment.name,
email: comment.email,
body: comment.body,
};
return postData
})
.then(createPost)
.then(newPost => {
console.log('새로운 댓글이 생성되었습니다:', newPost);
})
.catch(err => {
console.error('댓글 생성에 실패했습니다:', err);
});
자 이제 좀 볼만한 코드가 되었을 것이라 생각한다. api호출 함수는 따로 선언이 되어있으며, 위에서 아래로 흐르듯 코드가 작성이 되어있으며, 아무리 새로운 api함수가 호출이 추가 되어도, 콜백지옥까지는 코드가 늘어나지 않을 것이다.
하지만 이 코드에는 어떤 문제가 있을까?
getComments()
.then(/*...*/)
.then(/*...*/)
.then(/*...*/)
.catch(/*...*/);
console.log('여기 작성한 코드는???');
과연 저기 작성한 코드는 어떤 곳에 작성해야 할까? 즉 코드의 작성이 비동기/동기 부분으로 나누어지는 것이 가장 큰 문제이다.
Generator function
// generator function
function control(generator, args) {
return new Promise((resolve, reject) => {
const gen = generator(args);
recursion(gen);
function recursion(gen, params) {
const { value: promise, done } = gen.next(params);
if (done) {
promise.then((data) => resolve(data));
} else {
promise.then((data) => recursion(gen, data));
}
}
});
}
const getComments = () => {
return fetch('https://jsonplaceholder.typicode.com/comments')
.then(response => response.json());
};
const createPost = (postData) => {
return fetch('https://jsonplaceholder.typicode.com/comments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData),
})
.then(response => response.json());
};
control(function* () {
const comments = yield getComments();
console.log('여기 작성한 코드 1')
const comment = comments[0]; // 첫 번째 댓글 선택
console.log('comment', comment)
const postData = {
postId: comment.postId,
name: comment.name,
email: comment.email,
body: comment.body,
};
yield createPost(postData).then(newPost => {
console.log('새로운 댓글이 생성되었습니다:', newPost);
})
.catch(err => {
console.error('댓글 생성에 실패했습니다:', err);
});
console.log('여기 작성한 코드 2')
return Promise.resolve('success')
});
우와 코드가 엄청 길어졌는데요? 그리고 저 control이라는 함수는 뭐죠?
사실대로만 말하자면, Generator function만을 이용한 비동기로 api를 호출하는 경우, Promise보다 못한 코드가 되어 버린다. 따라서 그때 우리는 "co"와 같은 라이브러리를 같이 사용 했던것을 기억 할 것이다.
async/await
const getComments = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/comments')
return response.json()
};
const createPost = async (postData) => {
const response = await fetch('https://jsonplaceholder.typicode.com/comments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData),
})
return response.json()
};
async function main() {
const comments = await getComments();
console.log('여기 작성한 코드 1')
const comment = comments[0]; // 첫 번째 댓글 선택
console.log('comment', comment)
const postData = {
postId: comment.postId,
name: comment.name,
email: comment.email,
body: comment.body,
};
try {
const newPost = await createPost(postData)
console.log('새로운 댓글이 생성되었습니다:', newPost);
} catch(err) {
console.error('댓글 생성에 실패했습니다:', err);
}
console.log('여기 작성한 코드 2')
}
main();
댓글
댓글 쓰기