(11) Asynchronous JavaScript - then() 메소드

반응형

Promise를 다루는 방법에 대해 두 가지가 있다고 했을 떄,

https://seop-e.tistory.com/209

 

(6) Asynchronous JavaScript - Promies 다루는 방법

Promise 다루는 방법은 크게 두가지 있다.async 함수와 await 문법then() 메소드 + Callback먼저 async 함수와 await 문법을 다뤄보자await 문법fetch 함수는 Promise 객체를 리턴한다고 했을 때비동기 작업이 완

seop-e.tistory.com

  1. async 함수와 await 문법
  2. then() 메소드 + Callback

then 메소드를 이용해서 Promise를 다뤄보자.


then() 메소드

자바스크립트에서 비동기 코드를 잘 활용하려면

async, await, then 전부 다 알고 있는 것이 좋다.

 

then 메소드는 앞선 비동기 작업을 완료되면 등록된 콜백을 실행해준다.

한번 그 예시를 들여다보자.

// main.js
async function printList () {
    const response = await fetch('https://todo-api.fesp.shop/api/todolist');
    const data = await response.json()
    console.log(data);
}

오류 처리 하지않는 printList 함수에서 

함수의 내용을 then 문법으로 바꿔보면 다음과 같다.

// main.js
async function printList () {
    const response = await fetch('https://todo-api.fesp.shop/api/todolist');
    const data = await response.json()
    console.log(data);
}

// then()
const dataPromise = fetch('https://todo-api.fesp.shop/api/todolist').then((response)=> response.json());
dataPromise.then((data)=> console.log(data));

fetch는 Promise를 리턴한다고 했을 때,

then은 Promise 객체의 메소드이기 때문에

뒤에 .then((response)=> response.json()); 라고 이어서 쓸 수 있다.

 

그리고 then 메소드 자체도 Promise를 리턴하는데

한번 dataPromise를 출력해보면 Promise pending 이 출력된다.

// then()
const dataPromise = fetch('https://todo-api.fesp.shop/api/todolist').then((response)=> response.json());
console.log(dataPromise);

// dataPromise.then((data)=> console.log(data));

그래서 dataPromise 뒤에도 then 메소드를 붙일 수 있는 것이다.


// then()
const dataPromise = fetch('https://todo-api.fesp.shop/api/todolist').then((response)=> response.json());

dataPromise.then((data)=> console.log(data));

 

then 메소드는 앞선 비동기 작업을 완료되면 등록된 콜백을 실행해준다고 했을 때,

response가 돌아오면 ((respone) => response.json()) 콜백을 실행하고

response.json이 완료되면 ((data) => console.log(data)) 콜백을 실행하는 것이다.

그래서 코드를 실행해보면 데이터가 잘 출력 되는 것을 확인할 수 있다.


Promise Chain

그런데 뭔가 코드가 너무 길어보이는 감이 없지 않아있다.

즉 코드를 조금 더 간결하게 다음과 같이 작성할 수 있다

const dataPromise = fetch('https://todo-api.fesp.shop/api/todolist')
    .then((response)=> response.json())
    .then((data)=> console.log(data));

then은 Promise를 리턴 한다고 했으니

then 뒤에 바로 then을 또 붙일 수 있는 것이다.

이렇게 Promise 뒤에 메소드를 계속 연결해서 쓰는 것을 Promise Chain (프로미스 체인)이라고 한다.

실행해보면 똑같이 데이터가 잘 출력되는 것을 확인할 수 있다.


그럼 이제 코드의 원리에 대해 살펴보자.

일단 이미지에 dataPromise 라는 변수가 있는데 없다고 가정한다.

fetch 함수는 URL로 request를 보내고 곧바로 promise를 리턴한다.

그리고 이어서 then 메소드들도 Promise를 바로 리턴한다.

이때 안에 있는 콜백을 실행하는 것은 아니고 

일단 Pending 상태의 Promise를 리턴하는 것.

 

기다리다가 requset가 완료돼서 response가 돌아오면

첫 번째 Promise는 Fulfilled 상태가 된다.

Promise가 Fulfilled 상태가 되면 then 메소드에 등록된 콜백이 실행된다.

 

그리고 이때 Promise의 결과값을 콜백의 첫 번째 파라미터로 전달한다.

그래서 response가 콜백으로 전달되는 것이다.

 

만약에 콜백이 Pormise를 리턴하면 

then 메소드가 리턴한 Promise도 동일한 상태와 결과값을 갖게된다.

 

콜백이 Promise가 아닌 평범한 값( ex ) 1, 'foo')을 리턴하면

then 메소드가 리턴한 Promise는 Fulfilled 상태가 되고 

리턴 값을 결과값으로 갖게된다.

지금의 경우에는 response.json을 리턴하니까

response.json이 Fulfilled 상태가 되면

then 메소드가 리턴한 Promise도 Fulfilled 상태가 된다.

Fulfilled 상태가 되면 다음 then 메소드에 등록된 콜백이 실행되는데

파싱 결과가 첫 번째 파라미터로 전달된다.

이 콜백은 데이터를 출력하고 console.log를 리턴하는데

console.log는 undefined를 리턴하기 때문에

결국 콜백은 undefined를 리턴하는 것이다.

그래서 마지막 Promise는 Fulfilled 상태가 되고

undefined를 결과값으로 갖게되는 것이다.

그런데 지금 이 Promise에 무언가를 이어서 하지 않을 것이기 때문에

마지막 Promise에 대해서는 신경 쓰지 않아도 된다.


프로미스 체인의 중요한 점은 

비동기 작업을 기다리는 동안에는 다른 코드를 먼저 실행한다는 것인데

// then()
fetch('https://todo-api.fesp.shop/api/todolist')
    .then((response)=> response.json())
    .then((data)=> console.log(data));

    console.log('Task 2');
    console.log('Task 3');

예를들어 Task2와 3을 추가해보면

Task 2랑 3이 먼저 출력되고 데이터가 출력되는 것을 확인할 수 있다.

 

실행 순서를 되짚어 보자면..

 

먼저 fetch 함수가 Promise를 리턴하고

Promise가 Pending 상태인 동안 Task 2,3을 실행한다.

그리고 response가 돌아와서 Promise가 Fulfilled 상태가 되면

response를 가지고 첫 번째 then 메소드의 콜백을 실행한다.

 

콜백은 Promise를 리턴하고 

첫 번째 then 메소드의 Promise가 Fulfilled 상태가 될 때 까지

나머지 코드를 먼저 실행하는데 더이상 코드를 실행할 것이 없기 때문에

잠시 기다렸다가 Promise가 Fulfilled 상태가 되면

Promise의 결과값 즉, parsing 결과로 두 번째 then 메소드의 콜백을 실행한다.

그래서 데이터가 출력되고 프로그램은 종료된다.

 

중요한 점은 Promise가 Fulfilled 상태가 되면 = 비동기 작업이 끝나면

다음 then 메소드에 등록되어 잇는 콜백이 성공 결과값을 가지고 실행 된다는 것이다.

 

 

 

 

반응형