Programming/JS

[JavaScript] 7. JS 심화 문법(2) Promise

코딩하는 포메라니안 2022. 5. 4. 15:25

1. Promise란?

자바스크립트에서 비동기를 처리할 때, 동기처럼 처리하기 위해 사용하는 객체를 말한다.

비동기 처리가 끝난 후, 실행되어야 하는 것을 정의해놓고 비동기 처리가 끝나면 불려질 수 있도록 한다.

말 그대로, "넌 비동기 처리 끝나고 실행해줄게"하는 약속을 맺는다고 보면 된다.

 

 

비동기 처리 시

아래의 코드처럼 특정 로직이 끝나는 걸 기다리지 않고,

뒤의 로직을 바로 실행시키기 때문에 원하는 결과를 얻을 수 없다.

let data;

setTimeout(() => {
  data = 20;
  console.log('비동기 코드 실행 완료');
}, 3000);

console.log(data);
//undefined
//비동기 코드 실행 완료

 

 

이를 해결하는 방법은 대표적으로 콜백함수가 있고, 지금 보고 있는 Promise가 있다.

 

콜백함수는 비동기 처리 후, 실행할 문장을 함수인자로 넘겨서 비동기 처리 후에 실행하도록 한다.

콜백함수를 사용할 경우, 콜백지옥이 생길 수 있어 코드 가독성이 떨어질 수 있다.

 

*콜백지옥

더보기

순서대로 진행되어야 하는 코드들은 아래와 같이 콜백 => 콜백 => 콜백해서 계속 부른다.

$.ajax({
  //값 받아온 후에
  success({
    $.ajax({
      //유효값 검사 후에
      success: function(){
        //데이터를 줘야하는 client들을 찾아서 전달
      }
    })
  })
});

 

function getData(callbackFunc){
  setTimeout(() => {
    let data = 20;
    callbackFunc(data); //3초 후에, callback 함수에 값을 넘겨주어 실행시킨다.
    console.log('비동기 코드 실행 완료');
  }, 3000);
}

//비동기 처리 후, 실행할 문장을 함수로 만들어 callbackFunc으로 넣어준다.
getData(function(result){
  console.log(result);
})

 

 

 

2. Promise 사용법

기본적인 형식은 아래와 같다.

new Promise(function(resolve, reject){//콜백함수
    //성공시 resolve함수 실행
    //실패시 reject함수 실행
})

 

 

1. Promise 객체를 변수로 사용

.then을 여러번쓸 때, 중간에 catch로 걸리지 않는다면 앞에서부터 차례로 다 실행된다.

이는 switch문에 break가 없을 때와 유사하다고 볼 수 있다.

콜백지옥을 then을 여러번 써서 구현할 수 있게 된 것이다.

const promise = new Promise((resolve, reject)=>{
  //비동기 코드 호출
  setTimeout(() => {
    let data = 20; //데이터 있음
    //let data; //데이터 없음
    if(data){resolve(data);}
    else{reject("실패")}

    console.log('비동기 코드 실행 완료');
  }, 3000);
});

promise
.then((data)=>{
  console.log(data);
})
.then(()=>{
  console.log("2번째 then");
})
.catch((data)=>{
  console.log(data);
})
.finally(()=>{
  console.log("finally는 무조건 마지막에 실행됨");
})

 

 

2. Promise 객체를 반환값으로 사용

자기자신을 다시 호출(재귀)하는 것이 가능해짐

function test(url, params){
  return new Promise((resolve, reject)=>{
    console.log(`${url} ${params.method} 방식으로 호출`);

    setTimeout(() => {
      let data;
      if(params.method=='GET'){ data = 20;}

      if(data){resolve(data);}
      else{reject("실패")}

      console.log('비동기 코드 실행 완료');
    }, 3000);
  })
}

test("localhost:8080", {
  method: "GET",
  data:{
    id:"admin",
    name: "관리자",
    age: 20
  }
})
.then((data)=>{
  console.log(data);
})
.then(()=>{
  return test("localhost:8080",{method: "POST"});//재귀
})
.catch((data)=>{
  console.log(data);
})

 

 

3. Promise 커스터마이징하기

Promise를 내가 직접 만들어낼 수 있다.

단, 위의 방식들과는 반대로 비동기 함수 내에 실행할 함수를 등록하는 형태이다.

//비동기 실행 후, 실행해야 하는 문장
const myPromise ={
  then: function(num){
    console.log(num);
    return this;
  }
}

//비동기 코드
setTimeout(function () {
  myPromise.then(1).then(2).then(3);
}, 3000);