본문 바로가기

Front-End: Web/JavaScript

[코딩애플] js part 3-5. ES6 Promise

반응형

인간의 언어로 설명하는 ES6 Promise

사용 방법

콜백함수 만드는 거랑 비슷한데, 콜백함수보다는 약간 기능이 더 많다.

  • 옆으로 길어지지 않아서 굳
  • 실패할 경우에도 코드실행 가능 (catch)
    • 일반 콜백함수 : 1번 실행 후 2번 실행해주세요~
    • Promise로 만든 거 : 1번 실행 후 성공시 2번 실행해주세요~ 실패시 3번 실행해주세요~
var 프로미스 = new Promise();

프로미스.then(function(){ // 프로미스가 성공일 경우 실행할 코드
    
}).catch(function(){ // 실패할 경우에 실행할 코드
    
}).finally(function(){ // 성공이든 실패든 결과가 났을 때 실행할 코드
    
})

Promise = 성공/실패 판정 기계

그래서 성공, 실패 판정을 내가 판정을 해줘야 한다.

Promise 디자인하는 법

var 프로미스 = new Promise(function(성공, 실패){
    성공(); // 성공 판정 내리는 법
    실패(); // 실패 판정 내리는 법
});

프로미스.then(function(){ // 성공 판정되면 실행됨
    
}).catch(function(){ // 실패 판정되면 실행됨
    
});

Promise 예시 1

예제로 살펴보자. Promise는 비동기가 일어났을 때 순차적으로 코드를 실행하고 싶을 때 콜백함수 없이 쓰고 싶은 경우에 쓴다고 했다\(복습).

어려운 연산이 끝나면 특정 코드를 실행하고 싶다 하자.

var 프로미스 = new Promise(function(성공, 실패){
    var 어려운연산 = 1 + 1;
    성공();
});

프로미스.then(function(){
    console.log('성공했어요');
}).catch(function(){
    console.log('실패했어요')
});

자바스크립트는 동기적이니까 순차적으로 어려운연산을 실행하고 성공()을 실행한다.그래서 위의 코드는 '성공했어요'를 콘솔띄운다.

근데 만약 성공() -> 실패()로 변경하면 '실패했어요'가 콘솔뜬다.

Promise 장점

  1. 콜백 대신 예쁜 코드
  2. 성공/실패의 경우에 맞춰 각각 다른 코드 실행 가능

성공/실패시 데이터 전달하기

var 프로미스 = new Promise(function(성공, 실패){
    var 어려운연산 = 1 + 1;
    성공(10); // then 함수에 파라미터로 전달해줌
});

프로미스.then(function(결과){
    console.log(결과);
}).catch(function(){
    console.log('실패했어요')
});

위 코드를 실행하면 콘솔로 10이 뜬다.

Promise 예시 2

1초 후에 성공하는 Promise, 그리고 성공 시 특정 코드를 실행하고 싶다.

var 프로미스 = new Promise(function(성공, 실패){
    setTimeout(function(){
        성공();
    }, 1000)
});

프로미스.then(function(){
    console.log('성공했어요');
}).catch(function(){
    console.log('실패했어요.')
});
  1. 프로미스 기계 발동!
  2. 1초 후에 성공() 실행
  3. then() 실행
  4. 성공했어요 콘솔 반환

Promise의 3가지 상태

위 코드를 실행하고나서 프로미스를 찍어보면 '**resolved**'라 뜬다.

프로미스; // Promise {<resolved>: undefined}

프로미스는 세 가지 상태가 있다.

  1. 성공하면 <resolved>
  2. 성공/실패 판정 대기중이면 <pending>
  3. 실패하면 <rejected>

내가 작성하는 결과에 따라서 상태가 바뀐다. 프로미스 상태가 resolved면 then()을 실행하고, rejected 상태면 catch()를 실행한다. 이렇게 프로미스를 찍어보고 성공/실패 상태를 확인할 수 있다.

1초가 흐르기 전에 프로미스를 찍어보면 <pending>, 1초 후에 찍어보면 <resolved>가 뜬다.

Promise에 대한 오해

**promise는 동기를 비동기 처리로 가능하게 바꿔주는 마법의 문법이 아니다**.

그냥 **콜백함수 디자인의 대체품**, 코딩 스타일일 뿐이다.

Promise가 적용된 곳들

jQuery.ajax()

$.ajax().done(function(){}).fail() -> 생긴게 Promise랑 비슷하다

fetch()

fetch().then().catch() -> fetch를 하고나면 Promise가 return된다

연습 문제

Q1. <img> 이미지 로딩 성공시 특정 코드를 실행하고 싶습니다.

HTML 안에 있는 이미지 로딩이 끝나면 무언가 코드를 실행하고 싶습니다.

 

이 이미지가 로드가 되면 콘솔창에 성공, 로드가 실패하면 콘솔창에 실패를 출력하고 싶은데

Promise 문법의 then, catch 함수를 사용해 만들고 싶습니다. 어떻게 코드를 짜면 될까요?

(참고) 이미지 로딩이 끝났다는 것은 <img>에 load라는 이벤트리스너를 붙여서 체크가 가능합니다.

(참고) 이미지 로딩이 실패했다는 것은 <img>에 error라는 이벤트리스너를 붙여서 체크가 가능합니다.

➡️

var 이미지로딩 = new Promise(function (resolve, reject) {
  var img = document.querySelector("#test");

  img.addEventListener("load", function () {
    resolve();
  });

  img.addEventListener("error", function () {
    reject();
  });
});
이미지로딩.then(function(){
    console.log('로딩 성공')
}).catch(function(){
    console.log('로딩 실패')
})

Q2. Ajax 요청이 성공하면 무언가 코드를 실행하고 싶습니다.

https://codingapple1.github.io/hello.txt 라는 경로로 GET 요청을 하면 인삿말이 하나 딸려옵니다.

여기로 GET 요청을 해서 성공하면

Promise의 then 함수를 이용해서 Ajax로 받아온 인삿말을 콘솔창에 출력해주고 싶습니다.

어떻게 하면 될까요?

(jQuery done함수 자체에 Promise 기능이 있기 때문에 코드가 약간 중복도 많고 쓸데없을 수 있지만 연습삼아 해봅시다.)

이것은 jQuery Ajax 편리하니까 jQuery CDN 파일

➡️

const url = "https://codingapple1.github.io/hello.txt";

var hello = new Promise(function (resolve, reject) {
  $.get(url).done(function (res) {
    resolve(res);
  });
});

hello.then(function (res) {
  console.log(res);
});

Q3. Promise chaining - Ajax 요청 성공 시 또 다른곳으로 Ajax 요청하기

2번 문제에서 https://codingapple1.github.io/hello.txt 라는 경로로 GET 요청을 한 뒤에

.then을 이용해 인삿말을 콘솔창에 출력해보았습니다.

이번엔 그 직후 https://codingapple1.github.io/hello2.txt 라는 경로로 GET 요청을 또 하고

.then을 이용해 인삿말을 또 출력해보고 싶습니다.

쉽게 말하면

**1. hello.txt GET 요청**

**2. 그게 완료되면 hello2.txt GET 요청**

**3. 그게 완료되면 hello2.txt 결과를 콘솔창에 출력**

을 하고 싶다는 말입니다.

2번에서 만든 코드를 어떻게 업데이트하면 될까요?

**힌트1) 프로미스.then(()=>{둘째실행할거}).then(()=>{셋째실행할거})**

**이렇게 then을 여러개 이어붙여 만들어봅시다.**

**힌트2) .then()은 당연히 new Promise()로 생성한 프로미스 오브젝트들에 붙일 수 있습니다.**

➡️

프로미스를 return해서 여러 개의 then()을 연달아서 붙여 쓸 수 있다. 그러면 단계적으로 프로미스를 실행시킬 수 있다.

const url = "https://codingapple1.github.io/hello.txt";
const url2 = "https://codingapple1.github.io/hello2.txt";

var hello = new Promise(function (resolve, reject) {
  $.get(url).done(function (res) {
    resolve(res);
  });
});

hello
  .then(function (res) {
    console.log(res);

    var hello2 = new Promise(function (resolve, reject) {
      $.get(url2).done(function (res) {
        resolve(res);
      });
    });

    return hello2; // hello2.txt.를 요청~
  })
  .then(function (res) { // hello2.txt 요청 성공하면 이거 실행~
    console.log(res);
  });

함수로 축약하기

const url = "https://codingapple1.github.io/hello.txt";
const url2 = "https://codingapple1.github.io/hello2.txt";

function ajax해주는함수(URL){
    return new Promise((성공, 실패) => {
        $.get(URL).done(function(결과)){
          성공(결과);
   	 	}
    })
}

var 프로미스 = ajax해주는함수(url1);

프로미스.then(function(결과){
    console.log(결과);
    
    return ajax해주는함수(url2);
}).then(function(결과){
    console.log(결과);
})
반응형