[NODE 강의] Promise

2021. 3. 24. 00:52Dev/Node

반응형

[클립명]

1. Promise

2. Promise Chaining, Promise All

3. async await

이번에는 자바스크립트의 promise에 대해서 알아보자. nodejs에서는 모든 이벤트들이 기본적으로 비동기 처리 방식으로 실행되기 때문에, promise 객체에 대해서는 조금이라도 알고 있어야 한다.

Promise

promise에 대해 간단히 알아보자. promise란 비동기 작업의 최종 완료 또는 실패를 나타내는 객체이다.

이게 무슨 말이냐면, 특정 코드가 실행되는 것이 끝날때까지 기다리지 않고, 다른 코드가 실행되는 비동기 처리 작업의 최종완료 or 실패한 시점을 컨트롤 할 수 있도록 도와주는 객체라고 생각하면 쉬울 것 같다.

화장실에서 소변을 볼 때, 우리는 아래와 같은 순서대로 소변을 본다.

① 지퍼릍 내린다.

② 소변을 본다.

③ 지퍼를 올린다.

우린 저 작업을 동기로 처리한다. 반드시 지퍼를 내리는 것을 기다린 후에 소변을 보고, 소변을 다 보면 지퍼를 올린다.

만약 이 작업을 비동기로 처리한다면 지퍼를 내리는 와중에 소변을 보기 시작하고, 소변을 다 보기도 전에 지퍼를 올리는 작업이 실행될 것이다. 우웩ㅋㅋ

그렇기 때문에 우리는 각각의 작업이 완료된 후에 다음 작업이 시작되도록 해야 하고, 그러기 위해서는 선행 작업이 완료되거나 실패하는 시점을 컨트롤 할 수 있어야 한다. 즉 이럴 때 사용하는 것이 promise이다. 

promise를 이용하면 반드시 1번 작업이 끝난 후에 2번 작업이 실행되는 것을 보장해준다.

 

Promise 만들기

Promise 객체는 new 키워드와 생성자를 사용해 만든다. 생성자는 매개변수로 두 가지 실행함수를 받아야 하는데, 첫 번째 함수(resolve)는 비동기 작업을 성공적으로 완료해 결과를 값으로 반환할 때 호출하고, 두 번째 함수(reject)는 작업이 실패하여 오류 원인을 반환 시 호출한다. 두 번째 함수는 주로 오류 객체를 받는다.

.then()을 이용하여 처리하니까, 콜백지옥 코딩을 하지 않아도 된다.

const test = new Promise((resolve, reject) => {
  // 비동기 작업이 성공하여 값을 반환할 때 사용될 값
  resolve("비트코인")       
  // 비동기 작업이 실패하여 값을 반환할 때 사용될 값
  reject("failure reason")
});

test.then((result) => {
    //화면에 '비트코인' 출력
	console.log(result);
});
//콜백지옥................우웩
doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

 

아래 코드 실행 시, "시작 START" 가 출력되고 2초 후에 "2초 지연"이 출력되고, 곧바로 "프라미스 이행완료"가 출력된다.

위에서 본 콜백지옥 함수 소스보다 직관적이고 분석하기 쉽다.

const waitFunc = new Promise((resolve, reject) => {
	console.log("시작 START");
    setTimeout(() => {
    	resolve(console.log('2초 지연'));
    }, 2000)
})

waitFunc.then(() => {
	console.log("프라미스 이행완료");
})

 

Promise Chaining

두 개 이상의 비동기 작업을 순차적으로 실행하여, 각각의 작업이 이전 단계 비동기 작업이 성공하고 나서 그 결과값을 이용하여 다음 비동기 작업을 실행하고자 할 때 promise chain을 이용할 수 있다. 이 때, then()을 여러번 사용하여 여러개의 콜백을 추가할 수 있다. (각각의 콜백은 순서대로 하나하나 실행됨)

then() 메서드를 호출하고 나면 새로운 프로미스 객체가 반환된다.

const first = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({first_title : 'FRIST의 제목'})
    }, 1000)
});

const two = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({two_title : 'TWO의 제목'})
    }, 5000)
});

//then()을 이용하여 차례대로 실행되도록 처리
first.then(result =>{
    console.log(result.first_title);
    return two;
}).then(result2 => {
    console.log(result2.two_title);
});

Promise All

각 의 promise 객체들을 모두 실행한 후에 다음 코드가 실행되도록 처리할 떄는 Promise.all을 사용한다. 아래와 같이 사용하면 된다.

 

const first = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({first_title : 'FRIST의 제목'})
    }, 1000)
});

const two = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({two_title : 'TWO의 제목'})
    }, 5000)
});

//promise객체들을 배열로 전달하여, first --> two가 모두 실행된 후에 아래 코드가 실행되도록 처리 
Promise.all([first, two]).then(result => {
	console.log(result[0].first_title);
    console.log(result[1].two_title);
});

 

생각해보기

아래 코드를 실행하면 결과는 어떻게 될까?

let promise = new Promise(function(resolve, reject) {
    resolve(1);
  
    setTimeout(() => resolve(2), 1000);
  });
  
  promise.then(result => {
      console.log(result);
  });
더보기

1이 출력된다. 

첫 번째 resolve/reject만 호출되기 때문에, 두 번째 resolve는 무시된다.

 

반응형