IT_susu
Promise 본문
1. 프로미스란?
http 통신의 결과를 우리 입맛에 맞게 처리할 때 비동기 처리를 위한 패턴방식중에 하나. es6에서 비동기 처리를 위한 패턴으로 도입하였으며 기존 콜백 패턴이 가진 단점을 보완하고 비동기 처리 시점을 명확하게 표현합니다.
promise는 비동기식 작업의 최종 완료 또는 실패를 나타내는 객체.
2. 배경
기존 비동기 처리를 위한 패턴의 불편함.
2.1 콜백 헬
비동기로 처리를 하게되면 동기로 처리해야하는, 즉 앞선 처리의 결과값으로 뒤에 처리를 해야할 때 처리순서를 보장할 수 없기에 콜백패턴을 사용한다. 그런데 이게 많아질수록 중첩이 많이 되고 복잡도가 올라가게 된다.
코드는 위에서 아래로 보는데 왼쪽에서 오른쪽으로 읽게되어 가독성도 많이 떨어진다.
따라서 아래 블로그와 같은 콜백헬에 빠진다.
https://hoonmaro.tistory.com/47
2.2 에러 처리의 한계
try catch 예외처리는 호출자(caller)의 방향으로 전파되는데 비동기함수의 콜백함수의 caller는 콜백의 부모 함수가 아니므로 try catch에서 잡아내지 못한다. ( 이미 비동기 함수의 호출자는 콜스택에서 사라졌다 )
3. 프로미스의 생성
생성자 함수를 통해 인스턴스화 함.
// Promise 객체의 생성
const promise = new Promise((resolve, reject) => {
// 비동기 작업을 수행한다.
if (/* 비동기 작업 수행 성공 */) {
resolve('result');
}
else { /* 비동기 작업 수행 실패 */
reject('failure reason');
}
});
promise 객체는 기본적으로 resolve(성공)와 reject(실패) 인수를 받게끔 설계되어있다.
따라서 우리가 만들 때 비동기 작업 수행을 성공하면 resolve를 실패하면 reject를 실행시키도록 구조를 짜준다.
3-1. promise 상태
promise 객체를 생성하면서 비동기 통신을 합니다. 꼭 promise객체를 return 해야합니다.
const promiseAjax = (method, url, payload) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify(payload));
xhr.onreadystatechange = function () {
// 서버 응답 완료가 아니면 무시
if (xhr.readyState !== XMLHttpRequest.DONE) return;
if (xhr.status >= 200 && xhr.status < 400) {
// resolve 메소드를 호출하면서 처리 결과를 전달
resolve(xhr.response); // Success!
} else {
// reject 메소드를 호출하면서 에러 메시지를 전달
reject(new Error(xhr.status)); // Failed...
}
};
});
};
4. 후속처리 메서드
이제 만든 비동기 함수를 실행하여 후속처리 메소드로 연결하여 사용하면 된다. promise객체가 갖는 상태에 따라서 후속처리 메소드를 통해 통신 결과물을 전달받아 처리합니다.
- then : 두 개의 콜백 함수를 인자로 전달 받는다. 첫번쨰 인자는 성공시 호출, 두번째 인자는 실패시 호출. promise반환
- catch : 예외(비동기 처리에서 발생한 에러, then 메소드에서 발생한 에러)가 발생하면 호출. promise 반환
function getPureJsAjaxWithPromise(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject('Error: ' + xhr.status);
}
}
};
xhr.open('GET', url);
xhr.send();
});
}
const typicodeUrl = 'https://jsonplaceholder.typicode.com/posts';
// then에서 reject까지 처리
getPureJsAjaxWithPromise(typicodeUrl+'/1')
.then(
response => console.log('response', response),
error => console.error('error', error)
);
// 에러발생
getPureJsAjaxWithPromise(typicodeUrl+'/9999')
.then(
response => console.log('response', response),
error => console.error('error in reject', error)
);
// then과 catch
getPureJsAjaxWithPromise(typicodeUrl+'/1')
.then(response => console.log('response', response))
.catch(error => console.error('error', error));
// 에러발생
getPureJsAjaxWithPromise(typicodeUrl+'/9999')
.then(response => console.log('response', response))
.catch(error => console.error('error in catch', error));
// then에서 reject와 catch 차이
getPureJsAjaxWithPromise(typicodeUrl+'/1')
.then(
response => { throw 'Throw Error!'} ,
error => console.error('reject', error)
)
.catch(error => console.error('catch', error))
소스출처 : https://hoonmaro.tistory.com/47
then 메소드의 두번째 인자로 들어오는 reject는 비동기 처리에서 발생한 에러(reject 함수가 호출된 상태)만을 캐치하고 catch메소드는 비동기 처리에서 발생한 에러 + then 메소드 내부에서 발생한 에러도 캐치합니다. 따라서 에러 처리는 catch메소드를 사용하는 것이 더욱 효율적입니다.
5. 프로미스 체이닝
기존의 콜백헬이 비동기함수의 처리 결과를 가지고 다른 비동기 함수를 호출할 때 함수가 중첩되어 복잡도가 높아지는 것이었습니다. 이를 해결하기 위해 프로미스는 제이쿼리처럼 체이닝 기법을 활용해 프로미스를 연결하여 사용하게 합니다.
이를 위해 then, catch메소드가 모드 프로미스를 반환하도록 하면 계속 이어서 사용할 수 있습니다.
6. 기타
프로미스의 정적 메소드 등의 내용이 더 남아있지만...추후에 공부하면 추가...
'[ javascript ] > modern javaScript' 카테고리의 다른 글
generator 제너레이터 (0) | 2019.08.21 |
---|---|
비구조화 할당, 해체할당, 구조분해 destructuring assignment (0) | 2019.08.05 |
Arrow function (0) | 2019.08.05 |
String 객체의 새로운 메서드 (0) | 2019.01.31 |
gulp (0) | 2019.01.15 |