일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 코드스테이츠
- 회고
- javascript
- 토익
- codestates
- 타입스크립트 올인원
- 리액트
- 프로그래머스
- 타임어택
- 파이썬
- programmers
- SQL 고득점 Kit
- LeetCode
- 제로초
- Async
- 렛츠기릿 자바스크립트
- 코어 자바스크립트
- 자바스크립트
- 알고리즘
- 백준
- 손에 익히며 배우는 네트워크 첫걸음
- 2주 프로젝트
- 4주 프로젝트
- 타입스크립트
- 리덕스
- 정재남
- python
- til
- 리트코드
- js
- Today
- Total
Jerry
promise란? 본문
이번 시간은 promise(프라미스 / 프로미스)에 대해서 알아보는 시간을 가지겠다.
JAVASCRIPT.INFO를 참고하여 정리를 해보았다!
promise
promise 객체는 다음과 같은 문법으로 만들 수 있다.
let promise = new Promise(function(resolve, reject) {
// executor (제작 코드, '가수')
});
new Promise에 전달되는 함수는 executor(실행자, 실행 함수)라고 부른다. executor는 new Promise가 만들어질 때 자동으로 실행되며 인수로 resolve와 reject라는 자바스크립트 자체적으로 제공하는 콜백을 즉각적으로 반드시 호출해야 한다.
resolve(value)는 에러 없이 성공적으로 일이 끝날 때, value와 함께 호출되며, reject(error)는 에러 발생 시 에러 객체를 나타낸다.
new Promise 생성자가 반환하는 promise 객체가 있는데, state, result라는 내부 프로퍼티를 갖는다.
state에는 pending(보류 / 대기) / fullfied(resolve 호출시)호출 시) / rejected(reject 호출 시)가 있다. result는 undefined에서 resolve가 호출될 때 value로, reject가 호출되면 error로 변한다.
참고로, 처리가 끝난 프라미스에 resolve와 reject를 호출하면 무시된다.
let promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("…")); // 무시됨
setTimeout(() => resolve("…")); // 무시됨
});
참고로, executor는 대개 비동기적인 동작을 수행하고, 약간의 시간이 흐른 뒤 resolve와 reject를 호출하는데, 꼭 이럴 필요까진 없으며 즉시 호출할 수 있다. 어떤 일을 시작하려고 했지만, 이미 일이 끝나 저장까지 된 경우에 사용할 수 있다고 한다.
let promise = new Promise(function(resolve, reject) {
// 일을 끝마치는 데 시간이 들지 않음
resolve(123); // 결과(123)를 즉시 resolve에 전달함
});
참고로, state와 result는 내부 프로퍼티이므로 개발자가 직접 접근할 수 없지만, .then /. catch /. finally 메서드를 사용하면 접근이 가능하다.
예를 들어, 프라미스로 비동기 처리 후에 관련 결과에 따라서 값을 처리하거나 에러 핸들링을 해야 하는데 혹은 하게 되는데... 이럴 때 사용할 수 있는 메서드가 then / catch / finally가 있는 것이다.
프라미스 핸들러 .then/catch/finally는 항상 비동기적으로 실행됩니다.
then
then 메서드의 첫 번째 인수로 프라미스가 이행됐을 때 실행되는 함수로 실행 결과를 받는다. 두 번째 인수는 프라미스가 거부됐을 때 실행되는 함수로 에러를 받는다.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
// resolve 함수는 .then의 첫 번째 함수(인수)를 실행합니다.
promise.then(
result => alert(result), // 1초 후 "done!"을 출력
error => alert(error) // 실행되지 않음
);
catch
에러가 발생한 경우만 다루고 싶을 경우 사용하는 메서드다.
프라미스에서 발생한 모든 에러를 다루며, reject()가 호출되거나 에러가 던져지면 .catch에서 이를 처리한다.
물론,. then(null, errorHandlingFunction)같이 null을 첫 번째 인수로 전달하면 되긴 하지만 이보다 catch 매소드가 주로 선호되는 것 같다.
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("에러 발생!")), 1000);
});
// .catch(f)는 promise.then(null, f)과 동일하게 작동합니다
promise.catch(alert); // 1초 뒤 "Error: 에러 발생!" 출력
new Promise(function(resolve, reject) {
setTimeout(() => {
throw new Error("에러 발생!");
}, 1000);
}).catch(alert);
finally
프라미스가 이행이 되거나 거부가 되면, 무조건 실행된다는 점에서 finally는. then(f, f)와 유사하다. 쓸모 없어진 로딩 인디케이터를 멈추는 경우 같이, 결과가 어쨌든 마무리해야 할 경우 유용하다.
new Promise((resolve, reject) => {
/* 시간이 걸리는 어떤 일을 수행하고, 그 후 resolve·reject를 호출함 */
})
// 성공·실패 여부와 상관없이 프라미스가 처리되면 실행됨
.finally(() => 로딩 인디케이터 중지)
.then(result => result와 err 보여줌 => error 보여줌)
하지만, 차이점이 존재한다.
finally 핸들러에는 인수가 없다. 단지, 보편적 동작만 수행하기 때문이어서 그렇다. 그래서 프라미스 상태(이행 / 거부)가 어떻게 되었는지 알 수도 없다.
new Promise((resolve, reject) => {
throw new Error("에러 발생!");
})
.finally(() => alert("프라미스가 준비되었습니다."))
.catch(err => alert(err)); // <-- .catch에서 에러 객체를 다룰 수 있음
프라미스 체이닝
이번엔 프라미스 체이닝(promise chaining)을 이용한 비동기 처리에 대해 알아보자.
프라미스 체이닝은 result가 .then 핸들러의 체인(사슬)을 통해 전달된다는 점에서 착안한 아이디어입니다.
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
}).then(function(result) { // (***)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});
.then 또는 catch/finally 핸들러(어떤 경우도 상관없음)가 프라미스를 반환하면, 나머지 체인은 프라미스가 처리될 때까지 대기합니다. 처리가 완료되면 프라미스의 result(값 또는 에러)가 다음 체인으로 전달됩니다.
이를 그림으로 나타내면 아래와 같습니다.
프라미스 체이닝이 가능한 이유는 promise.then을 호출하면 프라미스가 반환되기 때문이고 프라미스가 반환되기 때문에 .then을 호출할 수 있다.
초보자는 프라미스 하나에 .then을 여러 개 추가한 후, 이를 체이닝이라고 착각하는데, 이는 체이닝이 아닙니다.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
});
promise.then(function(result) {
alert(result); // 1
return result * 2;
});
promise.then(function(result) {
alert(result); // 1
return result * 2;
});
promise.then(function(result) {
alert(result); // 1
return result * 2;
});
프라미스 API
Promise 클래스에는 5가지 정적 메서드가 존재한다.
이 중에서 Promise.all을 실무에서 가장 많이 사용한다고 한다.
Promise.all(promises)
- 모든 프라미스가 이행될 때까지 기다렸다가 그 결괏값을 담은 배열을 반환하는데, 주어진 프라미스 중에 하나라도 실패하면 Promise.all는 거부되며, 나머지 프라미스도 무시된다.
Promise.allSettled(promises)
- 모든 프라미스가 처리될 때까지 기다렸다가 그 결과를 담은 배열을 반환한다.
- status는 fullfilled / rejected
- value / 실패한 reason
Promise.race(promises)
- 가장 먼저 처리된 프라미스의 결과 또는 에러를 담은 프라미스 반환함
Promise.resolve(value)
- 주어진 값을 사용해 이행 상태 프라미스 만듦
Promise.reject(error)
- 주어진 에러를 사용해 거부 상태 프라미스 만듦
출처:
ko.javascript.info/promise-basics
ko.javascript.info/promise-chaining
ko.javascript.info/promise-error-handling
ko.javascript.info/promise-api
'Front > JavaScript' 카테고리의 다른 글
[JAVASCRIPT.INFO/Series #2]자바스크립트 기본(Javascript Basic) (0) | 2021.06.01 |
---|---|
[JAVASCRIPT.INFO/Series #1]자바스크립트란? (What is Javascript) (0) | 2021.05.30 |
이벤트 버블링(Event Bubbling), 이벤트 캡처링(Event Capturing), 이벤트 위임(Event Delegation), 이벤트 등록, 이벤트 흐름 정복하기!! (0) | 2021.04.28 |
함수 선언문과 함수 표현식(Function Declaration vs Function Expression) (0) | 2021.04.27 |
데이터 타입(Data Types) (0) | 2021.04.27 |