ajax를 통해 데이터를 가져오는 방법은 여러가지로 불편하다.
먼저, callback hell이 발생한다.
//ajax를 이용해 데이터를 가져오는 함수
const get= (url, successCallback, failCallback) => {
// ajax 동작
}
get("step1", () => {
get("step2", () => {
get("step3", () => {
//...
})
})
})
두번째로 에러처리에 한계가 있다.
다음과 같은 코드는 에러를 캐치하지 못한다.
try{
setTimeout(() => {throw new Error("Error"); }, 1000);
} catch(e) {
console.error("에러", e)
}
이러한 문제는 Promise를 사용하면 해결할 수 있다.
Promise
Promise는 ES6에서 도입된 표준 빌트인 객체이다.
promise는 아래와 같이 사용한다.
new Promise((resolve, reject) => {
if(/*처리 성공*/){
resolve("result")
} else {
reject("error")
}
})
Promise생성자에 arument로 콜백함수를 넘긴다. 이 콜백함수는 resolve, reject객체를 인수로 받는다.
처리가 성공하면, resolve에 결과를, 성공하지 않으면 reject에 결과를 담아주면 된다.
상태
Promise는 다음과 같은 상태정보가 있다.
pending : 요청이 아직 처리되지 않음.
fufilled : 요청 수행됨(성공) => resolve함수를 타면 fufilled가 됨
rejected : 요청 수행됨(실패) => reject함수를 타면 rejected가됨
settled : fullfiled나 rejected상태
Promise는 prototype으로 then, catch함수를 갖는다.
Then
then은 fullfiled이거나 rejected되면 호출된다.
new Promise(resolve => resolve("result"))
.then(v => console.log(v), e => console.log(e))
new Promise((_, reject) => reject("error"))
.then(v => console.log(v), e=> consoole.log(e));
catch
catch는 rejected되었을때 호출된다.
new Promise((_, reject) => reject("error"))
.catch(e => console.log(e));
then과 catch는 항상 Promise객체를 반환한다.
Promise객체를 return해주면 그 Promise객체를 그대로 반환하지만,
Promise가 아니면, Promise로 감싸서 보낸다.
finally
finally는 마지막에 항상 호출된다.
new Promise((_, reject) => reject("error"))
.finally(console.log("finally"));
Promise Chain
Promise Cahin을 연결할 수도 있다.
new Promise((res, rej) => res(1))
.then(data => data + 1) //then은 항상 promise를 return하므로 .then으로 체이닝 가능
.then(data => data + 1)
.catch(e => console.log(e));
이렇게 하면 첫번째 then에서 난 에러도 catch에서 잡힐 수 있다!!
위에서 만든 ajax함수에 promise를 도입해보자
const promiseGet= (url) => {
return new Promise((resolve, reject) => {
if(/* 성공 */){
// ajax 동작
resolve("result")
} else {
reject("error")
}
})
}
promiseGet(url)
.then( data => console.log(data))
.then( data => console.log(data))
.catch( e => console.log(e))
이제 콜백헬도, 에러 처리도 해결되었다.
ajax에서 Promise를 반환하도록 직접 짜도 되지만,
최근에 ajax이후에 나온 fetch API는 Promise를 반환하도록 되어있다.
fetch API를 써보는 것이 좋겠다. https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch
단, fetch는 404나 500같은 HTTP에러가 발생해도 에러를 reject하지 않고, 불리언 타입의 ok상태를 false로 설정한 response객체를 resolve한다. 네트워크장애나 cors에러에 의해 요청이 완료되지 못한 경우에만 프로미스를 reject한다는 단점이 있다. 따라서 resolve된 경우, 명시적으로 response.ok인지 체크해줘야한다.
이에 비해 Axios는 모든 에러에 대해 reject를 낸다.
fetch에서 제공하는 함수 말고도 다양한 함수를 제공하기 때문에 훨씬 많이 쓰인다.
Axios를 사용하기를 추천한다.
https://axios-http.com/kr/docs/intro
지금까지 Promise에 대해 알아봤다. 그런데 이렇게 콜백을 쓰는 패턴은 가독성이 좋지 않다.
쓰다보면 불편하다. 이걸 async await를 이용해 해결할 수 있다.
async await
async await를 사용하면 then/catch/finally 에 콜백함수를 전달해서 따로 처리할 필요 없이 마치 동기처리처럼 프로미스를 사용할 수 있게 한다.
async function fetchTodo() {
const url = "..."
const res = await fetch(url);
const todo = await res.json();
console.log(todo);
}
await는 비동기 처리가 완료될때까지 기다리라는 뜻이다.
await는 항상 async function안에서만 사용할 수 있다.
async function은 항상 Promise를 반환한다.
Promise를 반환하지 않으면, promise로 감싸서 반환한다
const bar = async n => n;
bar(2).then(v => console.log(v)); //2
'javascript' 카테고리의 다른 글
[javascript] Symbol이란? ES6에서 새로 추가된 타입, javascript enum (0) | 2022.09.23 |
---|---|
[vue] provide와 inject 알아보기 (0) | 2022.07.12 |
[JavaScript]ES6, Arrow Function, ES6 Method, Method (0) | 2022.06.20 |
[javascript] nested object deep copy, 중첩 Object 깊은 복사 (0) | 2022.06.09 |
[javascript] super의 역할 (0) | 2022.04.07 |