오늘의 과제는 버튼을 클릭하면 랜덤으로 그래디언트 배경을 뽑아주는 기능 구현이었다.
이전에 랜덤 컬러 뽑는 걸 한 번 연습해보기도 했고 별로 어렵진 않았다.

오늘은 봐도봐도 까먹는 프로미스를 다시 봤다...

// 콜백지옥의 예시
function taskA(a, b, cb) {
setTimeout(() => {
const res = a + b;
cb(res);
}, 3000);
}
function taskB(a, cb) {
setTimeout(() => {
const res = a * 2;
cb(res);
}, 1000);
}
function taskC(a, cb) {
setTimeout(() => {
const res = a * -1;
cb(res);
}, 2000);
}
taskA(3, 4, (a_res) => {
// 콜백지옥~~
console.log("task A : ", a_res);
taskB(a_res, (b_res) => {
console.log("task B : ", b_res);
taskC(b_res, (c_res) => {
console.log("tesk C : ", c_res);
});
});
});
// Promise 객체의 생성
const promise = new Promise((resolve, reject) => {
// 비동기 작업을 수행한다.
if (/* 비동기 작업 수행 성공 */) {
resolve('result');
}
else { /* 비동기 작업 수행 실패 */
reject('failure reason');
}
});
| 상태 | 의미 | 구현 |
|---|---|---|
| pending | 비동기 처리가 아직 수행되지 않은 상태 | resolve 또는 reject 함수가 아직 호출되지 않은 상태 |
| fulfilled | 비동기 처리가 수행된 상태(성공) | resolve 함수가 호출된 상태 |
| rejected | 비동기 처리가 수행된 상태(실패) | reject 함수가 호출된 상태 |
| settled | 비동기 처리가 수행된 상태 (성공 또는 실패) | resolve 또는 reject 함수가 호출된 상태 |
promise 생성자 함수가 인자로 전달 받은 콜백 함수는 내부에서 비동기 처리 작업을 수행한다.
성공하면 resolve 함수를, 실패하면 reject 함수를 호출한다. 이때 reject 함수의 인자로 에러 메시지를 전달한다.
이 에러 메시지는 Promise의 후속 처리 메서드로 전달된다!
function isPositiveP(number) {
const executor = (resolve, reject) => {
// executor -> 실행자, 비동기 작업을 실질적으로 수행하는 함수
setTimeout(() => {
// 성공 -> resolve
if (typeof number === "number") {
resolve(number >= 0 ? "양수" : "음수");
} else {
// 실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다");
}
}, 2000);
};
const asyncTask = new Promise(executor);
return asyncTask;
}
const res = isPositive(101);
res
.then((res) => {
console.log("작업 성공 : ", res);
})
.catch((err) => {
console.log("작업 실패 : ", err);
});
아까의 콜백지옥을 프로미스를 이용해서 다시 해보자
function taskA(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a + b;
resolve(res);
}, 3000);
});
}
function taskB(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * 2;
resolve(res);
}, 1000);
});
}
function taskC(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * -1;
resolve(res);
}, 2000);
});
}
const bPromiseResult = taskA(5, 1).then((a_res) => {
console.log("A result : ", a_res);
return taskB(a_res); // taskB의 값을 리턴했기 때문
});
console.log("비동기 처리 공부 중");
bPromiseResult
.then((b_res) => {
console.log("B result : ", b_res);
return taskC(b_res);
})
.then((c_res) => {
console.log("C result : ", c_res);
});
const wrongUrl = 'https://jsonplaceholder.typicode.com/XXX/1';
// 부적절한 URL이 지정되었기 때문에 에러가 발생한다.
promiseAjax(wrongUrl)
.then(res => console.log(res))
.catch(err => console.error(err)); // Error: 404
catch 메서드를 호출하면 내부적으로 then(undefined, onRejected)을 호출한다.
catch 메서드를 모든 then 메서드를 호출한 이후에 호출하면 비동기 처리에서 발생한 에러(reject 함수가 호출된 상태)뿐만 아니라 then 메서드 내부에서 발생한 에러까지 모두 캐치할 수 있다.
대충 봐도 then의 두번째 콜백으로 에러 처리를 하는 것보다는 catch를 사용하는 것이 가독성이 좋아보인다. 에러처리는 catch로만 하는 걸로!
따봉 캐치야 고마워!
-Promise.resolve와 Promise.reject 메소드는 존재하는 값을 Promise로 래핑하기 위해 사용한다.
정적 메소드 Promise.resolve 메소드는 인자로 전달된 값을 resolve하는 Promise를 생성한다.
const resolvedPromise = Promise.resolve([1, 2, 3]);
resolvedPromise.then(console.log); // [ 1, 2, 3 ]
const rejectedPromise = Promise.reject(new Error('Error!'));
rejectedPromise.catch(console.log); // Error: Error!
Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then(console.log) // [ 1, 2, 3 ]
.catch(console.log);
//첫번째 프로미스는 3초 후에 1을 resolve하여 처리 결과를 반환한다.
//두번째 프로미스는 2초 후에 2을 resolve하여 처리 결과를 반환한다.
//세번째 프로미스는 1초 후에 3을 resolve하여 처리 결과를 반환한다.
Promise.all([
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Error 1!')), 3000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Error 2!')), 2000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Error 3!')), 1000))
]).then(console.log)
.catch(console.log); // Error: Error 3!
// 가장 먼저 처리된 Error 3 이 콘솔로 찍힌다!
Promise.all([
1, // => Promise.resolve(1)
2, // => Promise.resolve(2)
3 // => Promise.resolve(3)
]).then(console.log) // [1, 2, 3]
.catch(console.log);
// Promise.all 에 전달 받은 이터러블 요소가 프로미스가 아닐 때, Promise.resolve를 통해 프로미스로 래핑할 수 있다.
Promise.race([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then(console.log) // 3
.catch(console.log);
비동기 처리는 왜 마주할 때마다 머리가 다 어질어질한지 모르겠다. 쉽지 않네ㅠㅠ) 그치만 중요한 개념이라고 하니 열심히 익혀야지..!
깃헙이랑 싸운 건 결국 내 패배인 것 같다...그래도 이제 커밋하고 푸쉬까진 할 수 있게 됐다....