비동기 작업 중 서버에서 데이터를 다 받기 전에 화면 랜더링 하는 것을 막기 위해 사용한다.
Promise의 3단계
Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
Rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태
먼저 아래와 같이 new Promise()
메서드를 호출하면 대기(Pending) 상태가 됩니다.
new Promise();
new Promise()
메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는 resolve
, reject
입니다.
new Promise(function(resolve, reject) {
// ...
});
여기서 콜백 함수의 인자 resolve
를 아래와 같이 실행하면 이행(Fulfilled) 상태가 됩니다.
new Promise(function(resolve, reject) {
resolve();
});
---
// resolve가 호출되면 3초 뒤 'OK'를 호출하는 함수
const p = new Promise(resolve, reject) => {
setTimeOut( () => {
resolve('OK') // reject(new Error('error..'))
}, 3000). // }, 3000)
} // reject 호출시 3초 후 'error..'를 반환
p.then( => p.then(
function(result) { } function(result) { }
function(err) { } ).catch(
) function(err){ }
)
그리고 이행 상태가 되면 아래와 같이 then()
을 이용하여 처리 결과 값을 받을 수 있습니다.
function getData() {
return new Promise(function(resolve, reject) {
var data = 100;
resolve(data);
});
}
// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function(resolvedData) {
console.log(resolvedData);// 100});
※ 프로미스의 '이행' 상태를 좀 다르게 표현해보면 '완료' 입니다.
new Promise()
로 프로미스 객체를 생성하면 콜백 함수 인자로 resolve
와 reject
를 사용할 수 있다고 했습니다. 여기서 reject
를 아래와 같이 호출하면 실패(Rejected) 상태가 됩니다.
new Promise(function(resolve, reject) {
reject();
});
그리고, 실패 상태가 되면 실패한 이유(실패 처리의 결과 값)를 catch()
로 받을 수 있습니다.
function getData() {
return new Promise(function(resolve, reject) {
reject(new Error("Request is failed"));
});
}
// reject()의 결과 값 Error를 err에 받음
getData()
.then()
.catch(function(err) {
console.log(err); // Error: Request is failed
});
그럼 위에서 배운 내용들을 종합하여 간단한 프로미스 코드를 만들어보겠습니다. 이해하기 쉽게 앞에서 살펴본 ajax 통신 예제 코드에 프로미스를 적용해보겠습니다.
function getData() {
return new Promise(function(resolve, reject) {
$.get('url 주소/products/1', function(response) {
if (response) {
resolve(response);
}
reject(new Error("Request is failed"));
});
});
}
// 위 $.get() 호출 결과에 따라 'response' 또는 'Error' 출력
getData().then(function(data) {
console.log(data);// response 값 출력}).catch(function(err) {
console.error(err);// Error 출력});
위 코드는 서버에서 제대로 응답을 받아오면 resolve()
메서드를 호출하고, 응답이 없으면 reject()
메서드를 호출하는 예제입니다. 호출된 메서드에 따라 then()
이나 catch()
로 분기하여 응답 결과 또는 오류를 출력합니다.
Source: 캡틴판교 - 자바스크립트 Promise 쉽게 이해하기 https://joshua1988.github.io/web-development/javascript/promise-for-beginners/#%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4-%EC%BD%94%EB%93%9C---%EC%89%AC%EC%9A%B4-%EC%98%88%EC%A0%9C
Promise.all() ⇒ 그냥 프로미스 체이닝보다 랜더링 시간 단축 가능 /
하나의 데이터라도 누락되면 어떠한 값도 얻을 수 없다. 따라서 무결점 검사에도 활용 가능
예시)
Promise.all([f1(), f2(), f3()])
.then((res) ⇒ {
console.log(res)
})
Promise.race() ⇒ 여러 프로미스 중 가장 먼저 완료된 프로미스만을 보여줌 (에러인 경우에도 동일)
사용법은 .all()과 동일
드림코딩엘리
Promise의 세가지 상태에 따른 활용, 개발자와 소비자의 차이를 이해하고 접근
새로운 promise가 생성되면 executor가 자동으로 실행되므로 불필요한 로드가 생길 수 있음
네트워크, 파일 읽기 등의 작업은 비동기환경에서 처리하는 것이 유리
const promise = new Promise((resolve, reject) => {
// 네트워크, 파일 읽기 등은 비동기적으로 처리하는 것이 유리
console.log('doing something...')
setTimeout(() => {
resolve('sun')
}, 2000)
});
// reject(new Error('no network')) => err
// }, 2000)
// 2. Consumers : then, catch, finally
// resolve가 호출될 시
promise.then((value) => {
console.log(value)
})
// reject가 호출될 시 catch로 error를 출력할 수 있음.
.catch(error => {
console.log(error)
})
.finally(() => console.log('fin'))
// 3. Promise Chaining
const fetchNum = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000);
})
fetchNum
.then(num => num *
.then(num => num * 3)
.then(num => { // 6
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num - 1) // 5
}, 1000);
})
})
.then(num => console.log(num)) // 5
// 4. Error Handling
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('🐔')
}, 1000);
})
const getEgg = hen =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`${hen} => 🥚`)
}, 1000);
})
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`${egg} => 🍳`)
}, 1000);
})
getHen()
.then(getEgg)
// .catch(error => {
// return '🍗'
// }) // 만약, getEgg 단계에서 에러 발생 시 🍗 => 🍳가 출력됨
.then(cook)
.then(console.log) // 🐔 => 🥚 => 🍳
async & await
// 1. async = function 앞에 붙이면 자동으로 Promise 형태로 return 해줌
async function fetchUser() {
// doing..
return 'fin'
}
const user = fetchUser()
// 2. await
function delay(ms) {
return new Promise(resolve => setTimeOut(resolve, ms))
}
async function getApple() {
await delay(1000)
return '🍎'
}
async function getBanana() {
await delay(1000)
return '🍌'
}
function pickFruits() {
return getApple()
.then(apple => {
return getBanana().then(banana => `${apple} + ${banana}`)
})
}
async function pickFruits() {
// 병렬적 진행
const applePromise = getApple()
const bananaPromise = getBanana()
const apple = await applePromise()
const banana = await bananaPromise()
return `${apple} + ${banana}`
}
pickFruits().then(console.log) // 🍎 + 🍌
// 3. Promise API
function pickAllFruits() {
return Promise.all([getApple(), getBanana()])
.then(fruits => fruits.join(' + ')
)
}
pickAllFruits().then(console.log) // 🍎 + 🍌
setTimeout(callback, millisecond)
일정 시간 후에 함수를 실행
setTimeout(function () {
console.log('1초 후 실행');
}, 1000);
// 123
setInterval(callback, millisecond)
일정 시간의 간격을 가지고 함수를 반복적으로 실행
setInterval(function () {
console.log('1초마다 실행');
}, 1000);
// 345
clearInterval(timerId)
반복 실행 중인 타이머를 종료
const timer = setInterval(function () {
console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// 더 이상 반복 실행되지 않음
(setTimeout
에 대응하는 clearTimeout
도 있음)
어려워