- 자바스크립트에서 제공하는 비동기를 간편하게 처리할 수 있는 object
- 정상 수행: 성공메세지와 함께 처리된 결과값을 전달한다.(
resolved
)- 실패: 에러를 전달한다.(
rejected
)- 프라미스는 성공 또는 실패만 한다.
- promise 이전에 비동기 통신을 할 때 사용되는
콜백함수
의 단점을 보완하기 위해 promise 객체가 생겨나게 됨
특정 함수 내에서 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출하는 함수
// 1초마다 숫자에 10을 더해준다. const _number10Add = (num, callback) => { setTimeout(() => { callback(num + 10); }, 1000); }; // 1초마다 숫자에 20을 더해준다. const _number20Add = (num, callback) => { setTimeout(() => { callback(num + 20); }, 1000); }; // 1초마다 숫자에 30을 더해준다. const _number30Add = (num, callback) => { setTimeout(() => { callback(num + 30); }, 1000); }; // 결과값을 콘솔에 출력한다. const _numberLog = (number) => new Promise(() => { setTimeout(() => console.log(number), 1000); }); // 최종 연산 값을 출력한다. => 반복 콜백 문제 발생 const resultConsole = () => { _number10Add(0, (callbackNum1) => { _number20Add(callbackNum1, (callbackNum2) => { _number30Add(callbackNum2, (callbackNum3) => { _numberLog(callbackNum3); }); }); }); }; resultConsole();
// 1초마다 숫자에 10을 더해준다. const _number10Add = (num) => { return new Promise((resolve) => { setTimeout(() => { resolve(num + 10); }, 1000); }); }; // 1초마다 숫자에 20을 더해준다. const _number20Add = (num) => { return new Promise((resolve) => { setTimeout(() => { resolve(num + 20); }, 1000); }); }; // 1초마다 숫자에 30을 더해준다. const _number30Add = (num) => { return new Promise((resolve) => { setTimeout(() => { resolve(num + 30); }, 1000); }); }; // 결과값을 콘솔에 출력한다. const _numberLog = (number) => new Promise(() => { setTimeout(() => console.log(number), 1000); }); // 최종 연산 값을 출력한다. const resultConsole = () => { _number10Add(0) .then((res) => _number20Add(res)) .then((res) => _number30Add(res)) .then((res) => _numberLog(res)); };
❗여기서 동기, 비동기의 차이란 무엇이냐면
ex) youtube 켬-> 데이터 불러오는 약 2초동안 화면에 아무것도 안뜸->사용자 입장에선 불편함😑..
✔️new Promise(executor)
->(promise의 형태)
- Promise를 생성하게되면 executor(실행함수)가 바로 실행된다.
executor
- Promise는 클래스 문법과 같이 new
키워드와 생성자를 사용해 만든다.
new
키워드와 생성자를 사용해 만듭니다. 생성자는 매개변수로 "실행 함수"를 받습니다. 이 함수는 매개 변수로 두 가지 함수를 받아야 하는데, 첫 번째 함수(resolve)는 비동기 작업을 성공적으로 완료해 결과를 값으로 반환할 때 호출해야 하고, 두 번째 함수(reject)는 작업이 실패하여 오류의 원인을 반환할 때 호출하면 됩니다. 두 번째 함수는 주로 오류 객체를 받습니다.const myFirstPromise = new Promise((resolve, reject) => { // do something asynchronous which eventually calls either: // (=둘 중 하나를 부르는 비동기적인 일을 한다) // resolve(someValue) // fulfilled(성공) // or // reject("failure reason") // rejected(실패) });
- Promise를 즉시 실행할 수도 있고 then
으로 호출하여 필요시에 사용할 수도 있다.
📖 Example(출처-https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise)
function myAsyncFunction(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.open("GET", url) xhr.onload = () => resolve(xhr.responseText) xhr.onerror = () => reject(xhr.statusText) xhr.send() }); }
- pending(대기): 초기 상태
- Fulfilled(이행): 성공적으로 완료된 상태
- Rejected(실패): 실패 상태
- 5초 뒤 안녕
찍히면서 상태 변함
✅Promise를 소비(사용)하는 .then
.catch
finally
promise .then((result)=>{ console.log(result) // 성공(정상작동일때 then메소드에서 값을 처리) }) .catch((error)=>{ console.log(error) // 실패(오류를 잡음) }) .finally(()=>{ console.log('성공이든 실패든 실행된다') })
const getApple = () => new Promise((resolve,reject)=>{ setTimeout(()=> resolve('🍎'), 1000) }) const getBanana = (apple) => new Promise((resolve,reject)=>{ setTimeout(()=>resolve(`${apple} => 🍌`), 1000) }) const getTrain = (banana) => new Promise((resolve,reject)=> { setTimeout(()=> resolve(`${banana} => 🚈`), 1000) }) // getApple() // .then((banana)=> getBanana(banana)) // .then((train)=> getTrain(train)) // .then((result)=> console.log(result)) getApple() .then(getBanana) .then(getTrain) .then(console.log) //'🍎 => 🍌 => 🚈'
const getApple = () => new Promise((resolve,reject)=>{ setTimeout(()=> resolve('🍎'), 1000) }) const getBanana = (apple) => new Promise((resolve,reject)=>{ setTimeout(()=>reject(new Error (`${apple} => 🍌`)), 1000) }) //getBanana 함수에서 Error를 입력함 const getTrain = (banana) => new Promise((resolve,reject)=> { setTimeout(()=> resolve(`${banana} => 🚈`), 1000) }) getApple() .then(getBanana) .catch((error)=> { return '🍍' }) //return 값으로 파인애플을 입력함 .then(getTrain) .then(console.log) //"🍍 => 🚈" (사과와 바나나는 없어지고 파인애플과 기차만 남음)
all
은 제일 늦게 끝나는 것 기준race
는 제일 빨리 끝나는 것 기준function timer(time) { return new Promise((resolve,reject)=> { setTimeout(()=>{ resolve(time) },time) }) } //비동기 로직으로 성공적으로 완료되어 time의 숫자를 결과값으로 반환한다. console.time('all') Promise.all([timer(1000), timer(2000), timer(3000)]).then((result)=> { console.log('result', result) console.timeEnd('all') }) //'result' [ 1000, 2000, 3000 ] //'all: 3001ms'
- 순서대로 실행되지만, 앞의 함수를 기다리지 않는다.
- 무조건 비동기 방식에서만 사용한다.
(그래서 비동기식으로 사용하지 않으면 그 데이터는 불러오지 못했기 때문에pending
상태로 불려짐)- 하나라도
reject
에 해당된다면 결과값은reject
값이 된다.
(ex. 하나라도 누락되면 페이지 안보여줄때 사용함)- 모든 promise를 실행한 후 진행되는 하나의 promise를 반환함✔️
function timer(time) { return new Promise((resolve,reject)=> { setTimeout(()=>{ resolve(time) },time) }) } //비동기 로직으로 성공적으로 완료되어 time의 숫자를 결과값으로 반환한다. console.time('all') Promise.race([timer(1000), timer(2000), timer(3000)]).then((result)=> { console.log('result', result) console.timeEnd('all') }) //'result' 1000 //'all: 1009ms'
- 동시에 트리거가 된다(약간의 차이 있음)
- promise.all: 마지막 기준
- promise.race: 처음 기준