resolve
, reject
의 의미와 then
, catch
와의 관계를 이해할 수 있다.Promise.all
의 사용법을 이해할 수 있다.
callback 함수는 오늘 배울 async
를 다룰 수 있게 도와주는 함수이기도 하며, 우리가 함수를 전달해주면 그 함수를 실행해주는 함수이다.
그래서 오늘 배운 코드는 에러가 났을 때, 앞에서 에러를 표시해주고 정상적으로 실행이 되었을 때 데이터를 반환하는 코드를 배웠다.
//생략..
// 먼저 파일을 불러왔다.
fs.readFile(filePath, "uft-8", function(err, data) {
// 만약 에러일 경우에는 에러를 반환한다.
if (err) {
return callback(err, null);
}
// 정상일 경우에는 데이터를 반환한다.
else {
return callback(null, data);
}
})
일단 먼저 에러일 경우를 반환해주는 조건문을 써주는게 좋다고 한다. 그래서 에러일 경우에는 콜백함수에 전달인자를 (err, null) 이런식으로 주었는데, err를 반환하면 data는 null
처리를 한 것이다.
만약 정상적으로 실행이 된다면 데이터를 반환하는데 전달인자는 (null, data)로 해주었다. 여기서 전달인자를 null
먼저 쓴 이유도 에러를 먼저 쓰기 때문이다.
에러 -> 데이터 순서는 관례적인 것 같다.
const printString = (string, callback) => {
setTimeout (() => {
console.log(string);
callback();
}),
Math.floor(Math.random() * 100) + 1;
}
const printAll = () => {
printString("A", () => {
printString("B", () => {
pintString("C", () => {})
})
})
}
위 코드는 콜백지옥이라고도 불리는데 저렇게 코드를 작성할 경우에는 가독성이 떨어질뿐더러, 어디서 에러가 났는지 찾기 힘들 것이다. 그리고 디버깅 또한 어려울 것이다.
그래서 오늘 Promise 를 배웠다.
Promise는 앞서 배웠던 callback
을 핸들링 하기 위한 테크닉이다.
Promise 는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용된다. Promise 는 자바스크립트에서 제공하는 것이고, 비동기를 간편하게 처리해주는 오브젝트이다.
그리고 또 좋은 점은 기능을 수행하다가 에러가 수행을 못할 경우 error를 보내준다.
Promise는 다음 두가지로 나눠 볼 수 있다.
Promise Producer
참고로 Promise는 클래스이다.
전달인자는 두가지가 있는데, Promise로 부터 기대한 값을 얻은 경우, resolve API를 사용하고, State: fulfilled가 된다.
reject API는 기대한 값으로 부터 값을 얻지 못한 경우 사용한다. 상태는 State: rejected가 된다.
// 생략..
return new Promise((resolve, reject) => {
fs.readFile(filePath, "utf-8", function(err, data) => {
// 에러 = reject
if (err) {
reject(err);
}
// 정상 = resolve
else {
resolve(data);
}
})
})
Promise Consumer
then은 Promise가 잘 수행이 되어서 최종적으로 resolve 콜백함수를 통해서 전달한 값이다.
catch는 Promise에서 에러가 났을 때 어떻게 처리할지 수행해주는 함수이다.
const printString = (string) => {
return new Promise((resolve, reject) => {
// ...
})
}
const printAll = () => {
printString("A")
.then(() => {
return printString("B");
})
.then(() => {
return printString("C");
})
}
printAll() // A B C
Promise도 .then()
안에서 return을 해주지 않으면 콜백지옥처럼 프로미스 지옥이 될수도 있으니 조심하자.
Promise.all
Promise.all은 모든 Promise
들이 병렬적으로 다 받을 때 까지 기다렸다가 다시 전달하게 해주는 함수이며, 전달인자는 객체인 배열로 받는다.
// 생략..
return Promise.all([
getDataPromise(user1),
getDataPromise(user2),
]).then((data) => {
// JSON으로 받은 data들을 map 함수를 통해 모두 다 객체로 다시 변환한다.
return data.map((el) => JSON.parse(el));
})
Async & Await 은 ES7
이후에 나온 것으로, 위에 배웠던 프로미스들을 더 읽기 쉽게 해준다.
즉, 동기식처럼 보이게 해주며 조금 더 간편한 API를 제공해준다. (syntactic sugar)
아래 좋은 예제 코드가 있다.
// URL을 가져와서 응답을 텍스트로 로그하려는 경우
function logFetch(url) {
return fetch(url)
.then(response => response.text())
.then(text => {
console.log(text);
}).catch(err => {
console.error('fetch failed', err);
});
}
다음 코드도 똑같은 결과를 낸다.
async function logFetch(url) {
try {
const response = await fetch(url);
console.log(await response.text());
}
catch (err) {
console.log('fetch failed', err);
}
}
await는 Async
가 있는 함수에서만 사용할 수 있으며, Promise.resolve() 를 통해서 전달이 된다.
오늘 한가지 깨달았던 점은 return await getDataPromise(user)… 이 부분에서 await는 바로 return으로 쓸 수 없다는 것이었다.
다행히 페어분께서 변수에 할당해서 하면 될 것이라고 말씀해주셔서 오늘 일정도 빠르게 끝낼 수 있었다.
자바스크립트를 배우는 과정에서 비동기는 정말정말 중요하다고 수 없이 들었다. 그래서 오늘 배웠던 부분을 일찍 끝마쳤지만, 복습은 꾸준히 할 예정이다. 문제들은 쉽게 풀었지만 막상 실제로 사용한다고 하면 많이 버벅거릴 것 같다.
아직도 다른 할 일이 많이 남았지만, 비동기는 틈틈히 공부해보자!
👊 내일의 TIW(today I Will)
fetch API