콜백함수 디자인패턴이 마음에 안 들고 가독성이 좋지않아 *콜백 헬에 갇혀졌을때
Promise 디자인패턴을 사용하면 좋다.
이건 자바스크립트의 새로운 기능이라기보다는 코드/함수 디자인 패턴일 뿐입니다.
var 프로미스 = new Promise();
프로미스.then(function(){
}).catch(function(){
});
new Promise() 문법으로 프로미스라는 변수 오브젝트를
하나 생성하시면 Promise 제작 끝!!
그럼 이제 프로미스라는 변수에다가 then()을 붙여서 실행가능합니다.
프로미스 안의 코드가 실행이 완료가 되었을 때 then()
함수 내의 코드를 실행시켜준다.
코드가 실행이 실패했을 경우엔 catch()
함수 내의 코드를 실행시켜준다.
콜백함수와는 다르게 순차적으로 뭔가를 실행할 때 코드가 옆으로 길어지지 않는다.
then
함수를 붙여서 순차적으로 실행하기때문.
콜백함수는 불가능한 '실패시 특정 코드를 실행해주세요~' 라고 코드를 짤 수 있다.. (catch)
성공하면 then(), 실패하면 catch()를 실행해줘
라는 코드를 짤 수 있게 도와주는게 바로 Promise이다.
그럼 Promise는 성공과 실패 상황을 알려줘야한다.
그래서 Promise를 를 쉽게 정의하자면 성공&실패 판정기계!!!
Promise 생성자 함수를 new 연산자와 함께 호출하면 프로미스(promise 객체) 를 생성한다.
Promise 생성자 함수는 비동기 처리를 수행 할 콜백함수를 인수로 받는데,
이 콜백함수는 resolve 와 reject를 함수를 인수로 받는다.
const Promise = new Promise((resolve,reject) => {
///Promise 함수의 콜백 함수 내부에서 비동기 처리를 수행한다.
if(/*비동기 처리 성공*/){
resolve('resolve')
}else{ /*비동기 처리 실패*/
reject('failure reason');
}
});
Promise생성자 함수가 인수로 전달 받은 콜백함수 내부에서 비동기 처리를 수행한다.
이떄 비동기 처리가 성공하면 함수의 인수로 받은 resolve 함수가 호출하
고, 실패하면 reject함수를 호출한다.
Promise 기계 안에는 아무거나 다 집어넣을 수 있다.
var Promise = new Promise(function(성공, 실패){
성공();
});
Promise.then(function(){
}).catch(function(){
});
Promise()안에 콜백함수를 하나 추가해주시면 그 안에서 성공/실패 판정을 내릴 수 있다.
<성공()이라고 첫째 파라미터를 함수형태로 작성하면 성공판정이 된다>
<실패()라고 둘째 파라미터를 함수형태로 작성하면 실패판정이 됩니다. >
위의 코드는 무조건 성공()을 실행하게 되어있으니 무조건 성공을 판정내리며
그 후엔 이제 then()안의 코드가 실행된다.
예제1)
var Promise = new Promise(function(성공, 실패){ var 어려운연산 = 1 + 1; 성공(); }); Promise.then(function(){ console.log('연산이 성공했습니다') }).catch(function(){ });
Promise()안에 수학 연산을 해주는 기능을 추가 해놓은 코드이다.
그리고 그 연산이 완료되면 성공() 코드를 실행하도록 코드를 추가했다.
(일반 코드들은 저렇게 위아래로 나란히 적으면 그냥 차례로 실행된다)
이제 프로미스 내의 1+1 이라는 어려운 수학연산이 완료되면 성공() 판정을 내리며,
성공시 then() 내의 코드를 실행해준다.
이렇게 Promise를 사용하시면 이상한 콜백함수패턴 대신 멋있는 then을 사용할 수 있다.
예제2
///GET요청을 위한 비동기 함수. const promiseGet = url =>{ return new Promise((resolve , reject)=>{ const xhr = new XMLHttpRequest(); xhr.open('GET',url); xhr.send(); xhr.onload = () => { if(xhr.status ===200){ ///성공적으로 응답을 전달받으면 resolve함수를 호출한다 resolve(JSON.parse(xhr.response)); }else{ //에러처리를 위해 reject 함수를 호출한다. reject(new Error(xhr.status)); } }; }; }; //promiseGet함수는 프로미스를 반환한다. promiseGet('https://jsonplaceholder.typicode.com/post/1')
비동기 함수인 promiseGET은 함수 내부에서 프로미스를 생성하고 반환한다.
비동기 처리는 함수가 인수로 전달받은 콜백함수 내부에서 수행한다.
만약 비동기 처리가 성공하면 비동기 처리 결과를 resolve 함수에 , 비동기 처리가 실패하면 reject 함수에 인수로 전달하며 호출한다
var 프로미스 = new Promise(function(성공, 실패){ var 어려운연산 = 1 + 1; 실패(); }); 프로미스.then(function(){ console.log('연산이 성공했습니다') }).catch(function(){ console.log('실패했습니다') }); ``
실패()라는 함수를 실행하는 순간 실패판정을 내린다.
그렇게 되면 catch() 내의 코드를 실행해준다
실패의 경우 다른 내용을 실행해줄 수도 있고하니 그냥 콜백함수 디자인보다 훨씬 뭔가 직관적이고 유용하다.
일단 new Promise()로 생성된 변수를 콘솔창에 출력해보시면 현재 상태를 알 수 있다.
성공/실패 판정 전에는 pending 이라고 나오며
성공 후엔 resolved
실패 후엔 rejected 이런 식으로 나온다
이렇게 프로미스 오브젝트들은 3개 상태가 있다.
그리고 성공을 실패나 대기상태로 다시 되돌릴 순 없다.
Promise는 동기를 비동기로 만들어주는 코드가 아닙니다.
Promise는 비동기적 실행과 전혀 상관이 없다.
그냥 코딩을 예쁘게 할 수 있는 일종의 디자인 패턴이다
예를 들면.. Promise 안에 10초 걸리는 어려운 연산을 시키면 10초동안 브라우저가 멈춘다
10초 걸리는 연산을 해결될 때 까지 대기실에 제껴두고 그런거 아닙니다.