본문 바로가기

JS/ECMAscript

프로미스 promise

프로미스는 비동기 처리에 사용되는 객체이다. 다른 코드의 실행이 완료될 때까지 기다리지 않고 다른 코드를 실행하는 것이다.


promise를 쓰는 이유

코드를 깔끔하게 하고 콜백 지옥을 방지한다.


한번 쭉 보고 넘어가면 된다.

new Promise(function(resolve, reject){
setTimeout(function() {
resolve(1);
}, 2000);
})
.then(function(result) {
console.log(result); // 1
return result + 10;
})
.then(function(result) {
console.log(result); // 11
return result + 20;
})
.then(function(result) {
console.log(result); // 31
});


위 코드에서 new Promise()로 객체를 생성하는데 인자로 resolve, reject가 있다. 그리고 resolve()를 호출하고 .then()이 나온다.


프로미스에는 3가지 상태가 있다. 프로미스의 3가지 처리 과정이 있다.

1. Pending 대기 : 비동기 처리 로직이 아직 미완료 상태

2. Fulfilled 이행 : 비동기 처리가 완료되어 프로미스가 결과 값을 반환한 상태

3. Rejected 실패 : 비동기 처리가 실패하거나 오류가 발생한 상태


Pending 대기

new Promise()를 호출하면 대기 상태가 된다.

new Promise() 메서드를 호출하면 콜백 함수의 인자로 resolve, reject에 접근할 수 있다.

new Promise(function (resolve, reject){})


Fulfilled 이행

콜백 함수의 인자 resolve를 호출하면 Fulfilled 상태가 된다.

new Promise(function (resolve, reject){
resolve()
})


resolve를 호출한 뒤 이행(완료) 상태가 되면 then()을 써서 처리 결과를 받을 수 있다.

getData()를 호출하고 new Promise()를 호출하여 대기 상태가 된다. 그리고 data는 1로 초기화되고 resolve에 data를 인자로 넘긴다. resolve가 호출되었으므로 완료 상태가 된다. resolve의 결과값 data가 반환되고 then()에서 resolvedData에 1이 할당된다.

function getData(){
return new Promise(function(resolve,reject){
var data = 1
resolve(data)
})
}

getData().then(function(resolvedData){
console.log(resolvedData)
})


Reject 실패

new Promise() 메서드 호출 시 resolved와 reject가 인수인데 resolved 메서드가 호출되면 완료지만 reject 메서드가 호출되면 실패다.

실패 상태가 되면 실패한 이유(실패 처리 결과 값)을 catch()로 받을 수 있다.

function getData(){
return new Promise(function(resolve,reject){
reject("reject입니다.")
})
}

getData().then().catch(function(err){
console.log(err)
})


Promise Flow

1. new Promise() 호출. pending (대기) 상태

2.

    (1) fulfill (충족)

    (2) reject (거절)

    <settled> 대기 상태가 아닌 충족이든 거절이든 결정된 상태

3. 완료 또는 실패에 대한 결과값 반환

4. then()에서 결과값 처리 또는 catch()에서 오류 결과 처리


예제

function getData() {
return new Promise(function (resolve, reject) {
var res='result';
if (res) {
resolve(res);
}
reject("에러");
});
}
// Fulfilled 또는 Rejected의 결과 값 출력
getData().then(function (data) {
console.log(data); // response 값 출력
}).catch(function (err) {
console.log(err); // Error 출력
console.err(err);
});

getData() 호출. new Promise 메서드 호출, 대기 상태. 변수 res에 '결과' 할당. res가 undefined 또는 null이 아니면 resolve() 호출 및 인수로 res 넘기기, 완료 상태. [만약 res가 undefined 또는 null일 시 reject 호출, 실패 상태]. 완료되었으므로 then에서 data 인자로 값 받아 출력


여러 개의 프로미스 연결 chaining

new Promise(function(resolve, reject){
setTimeout(function() {
resolve(1);
},4000);
})
.then(function(result) {
console.log(result); // 1
return result + 10;
})
.then(function(result) {
console.log(result); // 11
return result + 20;
})
.then(function(result) {
console.log(result); // 31
});

then() 메서드를 호출하면 프로미스 객체가 반환된다. 그러므로 계속해서 then()을 호출하는 것이 가능해진다.

then() 내에서 return을 하면 반환되는 값이 다음 then()으로 넘어가게 된다. 그래서 이전 then에서 이후의 then에 값을 넘길 수 있다.


https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then


에러 처리 방법

1. then()의 두번째 인자로 에러 처리

getData().then(
handleSuccess,
handleError
);


2. catch()

getData().then().catch();


두 방법 모두 프로미스의 reject 메서드가 호출됐을 때 실행된다.

function getData(v){
return new Promise(function(resolve,reject){
if (v){
    
}
reject('Error!!')
})
}

const v = false

getData(v).then(
function(){},
function(e){
console.log(e)
}
)

getData(v).then().catch(function(err){
console.log(err)
})


예외 처리 시 then()을 활용하기보다 catch()를 써야 하는 이유

function getData(v){
return new Promise(function(resolve,reject){
resolve()
})
}

getData(v).then(
function(){
    throw new Error('Error!')
},
function(e){
console.log(e.message)
}
)

getData(v).then(function(){
    throw new Error('Error!!')
}).catch(function(err){
console.log(err.message)
})


then()의 두번째 인자를 사용하면 에러를 잡지 못한다.

Uncaught (in promise) Error: Error!

    at eval (eval at value (sandbox.js:109), <anonymous>:8:11)


catch()를 사용하면 then()이 끝나고 catch()가 실행되기 때문에 에러를 잡을 수 있다.


https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

'JS > ECMAscript' 카테고리의 다른 글

ECMAScript6 온라인 실행 환경  (0) 2018.12.31
이터러블 프로토콜 iterable protocol  (0) 2018.12.30
이터레이터 프로토콜 iterator protocol  (0) 2018.12.30
for of  (0) 2018.12.30
forEach  (0) 2018.12.29