1. 프라미스
* 소개
- 제작 코드(producing code) : 원격에서 스크립트를 불러오는 것 같이 시간이 걸리는 코드
- 소비 코드(consuming code) : 제작 코드의 결과를 사용하는 코드
- 프라미스(promise) : 제작 코드와 소비코드를 연결해 주는 자바스크립트 객체
- 프라미스 문법은 다음과 같다.
let promise = new Promise(function(resolve, reject) {
// executor
});
- 실행자(executor)의 인수 resolve와 reject는 자바스크립트가 자체적으로 제공하는 콜백이다.
- 인수로 넘겨준 resolve와 reject중 하나를 반드시 호출해야 한다.
- resolve(value) : 성공적으로 일이 끝난 경우 결과를 value와 호출
- reject(error) : 에러 발생 시 에러 객체를 나타내는 error와 함께 호출
- new Promise생성자가 반환하는 프라미스 객체는 state와 result라는 내부 프로퍼티를 갖는다.
- state : 기본적으로 pending(보류)이며 resolve가 호출되면 fulfilled를, reject가 호출되면 rejected가 된다.
- result : 기본적으로 undefined이며 resolve(value)가 호출되면 value를, reject(error)가 호출되면 error가 된다.
* 사용
- 이제 promise생성자와 executor함수의 예시를 살펴보자. executor함수에는 즉시실행되는 함수를 넣을 수도 있지만 여러 요청을 보내는 상황을 가정하여 시간이 걸리는 setTimeout을 이용해보자.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("완료!"), 1000);
});
- 프라미스가 만들어지면 executor 함수는 자동으로 실행된다.
- executor가 처리되고 1초 후에 resolve("완료!")가 후출되어 결과가 만들어진다.
- 이 때의 프라미스 객체의 상태는 state가 pending에서 fulfilled로 바뀌고, result가 undefined에서 "완료!"로 바뀔 것이다.
- 위처럼 일이 성공적으로 처리되면 "fulfilled promise(약속이 이행된 프라미스)"라 부른다.
- 다음은 오류를 발생시키는 예시이다.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("오류!")), 1000);
});
- 이 때의 프라미스 객체의 상태는 state가 pending에서 rejected로 바뀌고, result가 undefined에서 "오류!"로 바뀔 것이다.
- 참고로 이미 처리된 프라미스에 resolve와 reject를 호출할 경우 모두 무시된다.
2. 메서드
* then
- 위에서 프라미스가 제작코드와 소비코드를 연결시켜 준다고 했었다. 여기서 소비코드는 then이나 아래에 나올 메서드들에 등록하여 사용한다.
- then의 문법은 다음과 같다.
promise.then(
function(result) {
// ...
},
function(error) {
// ...
}
);
- then의 첫 번째 인수는 프라미스가 제대로 이행되었을 때 실행되는 함수이다.
- then의 두 번째 인수는 프라미스가 에러를 발생시켰을 때 실행되는 함수이다.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("완료!"), 1000);
});
promise.then(
result => alert(result),
error => alert(error)
);
- 위를 실행하면 프라미스가 제대로 이행되었다고 판단하고 result에 "완료!"를 받아서 보여준다.
- 다음은 프라미스에서 에러가 났을 경우이다.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("오류!")), 1000);
});
promise.then(
result => alert(result),
error => alert(error)
);
// Error: 오류!
- 위의 경우 프라미스에서 에러가 났으며, error에 "Error: 오류!"가 담기게 된다.
- 만약 성공 케이스만 다루고 싶다면 두 번째 인자를 제외시킬 수도 있다.
* catch
- 위에서 성공 케이스만 다루고 싶을경우에 대해서 간단히 얘기했었다. 만약 실패케이스만 다루고 싶다면 어떻게 해야할까.
- 첫 번째 인자로 null을 넣어서 해도 좋지만 간단하게 catch를 쓰면 에러케이스만 다룰 수 있다.
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("오류!")), 1000);
});
promise.catch(alert);
// Error: 오류!
- 위는 .then(null, alert)와 완전히 동일하다.
* finally
- finally는 try catch에서 나왔던 것과 거의 동일하다. 즉 프라미스가 성공이든 에러든 항상 실행된다.
- 문법은 다음과 같다.
new Promise((resolve, reject) => {
// ...
})
.finally(() => /* ... */ )
.then(result => /* ... */ )
- finally 핸들러엔 인수가 없다. 즉 이 안에서는 프라미스가 성공인지 에러인지 알 수 없다. 물론 몰라도 되는 곳이다.
- 여기서 놀라운 점은 result나 error가 finally를 거쳐서 자동으로 아래로 전달된다는점이다.
- finally뒤에 catch로 에러를 다루더라도 정상적으로 작동한다.
* 프라미스 vs 콜백
- 우리는 이제 프라미스가 콜백보다 나은 것을 알고 있다. 이를 정리해보자.
- 콜백은 시간이 걸리는 작업을 호출할 때, 함께 호출할 callback함수를 미리 준비해야한다. (두 번째 인자에 넣음) 즉 호출 이전에 호출 결과로 무엇을 할 지 알고 있어야한다. 그러나 프라미스를 사용하면 .then에 코드를 작성하므로 흐름도 자연스럽고 가독성도 좋다.
- 콜백은 하나만 가능하지만 프라미스는 원하는 만큼 then을 호출할 수 있다.
참고
모던 자바스크립트 튜토리얼
'Language > JavaScript' 카테고리의 다른 글
<ES6> ES2015(ES6) Features (1) (0) | 2021.08.01 |
---|---|
<자바스크립트> 프라미스 체이닝과 에러 (0) | 2021.04.23 |
<자바스크립트> 콜백 (0) | 2021.04.19 |
<자바스크립트> try catch & 에러 (0) | 2021.04.16 |
<자바스크립트> 클래스의 기본과 상속 (0) | 2021.04.14 |