[JavaScript] Asynchronous - Promise chaining, Fetch

Steve·2021년 5월 26일
0

웹개발 코스

목록 보기
27/59

Promise chaining

  • 동기식 (just for practice)
  • 비동기식

Fetch


Promise chaining

동기식 (just for practice)

Promise 를 사용하여 숫자를 차례대로 1, 12, 123 출력해 보자.
.then 을 이어붙여 chaining 을 만들 수 있다.

new Promise((resolve, reject)=> {
  resolve('1');
})
.then(result => {
  console.log(result);
  return result + '2';
})
.then(result => {
  console.log(result);
  return result + '3';
})
.then(result => {
  console.log(result);
  return result;
})
// 1 12 123

알 수 있는 점:

  1. 맨 위 new Promise 는 내부적으로 resolve를 호출함으로써 { state "resolved", value: "1" } 인 Promise 객체가 된다. (이러한 객체가 "반환"된다.)
  2. 거기에 Promise 메서드인 then 을 써서 value 를 인자로 받을 수 있다. 이 값으로 필요한 작업을 수행한 후, '12'를 반환한다. 그러면 이 then{ state "resolved", value: "12" } 인 Promise 객체가 된다. (이러한 객체가 "반환"된다.)
  3. 여기에 다시 Promise 메서드인 then 을 써서 value 를 인자로 받는다. 이 값으로 필요한 작업을 수행한 후, '123'를 반환한다. 그러면 이 then{ state "resolved", value: "123" } 인 Promise 객체가 된다. (이러한 객체가 "반환"된다.)

이런 식으로 나아간다.

비동기식 (setTimeout 활용)

위 코드를 setTimeout 을 활용하여 비동기적으로 만들어보자:

틀린 예시

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('1');
  }, 2000)
})
.then(result => {
  setTimeout(() => {
    console.log(result);
    return result + '2';
  }, 2000)
})
.then(result => {
  setTimeout(() => {
    console.log(result);
    return result + '3';
  }, 2000)
})
.then(result => {
  setTimeout(() => {
    console.log(result);
    return result;
  }, 2000)
})
// 1 undefined undefined

위 코드가 실패하는 이유:

이미 Setteled 된 Promise 에 return 을 하고 있기 때문에 새로운 비동기 작업을 할 수 없다.

함수의 작동:

  1. 처음에는 2초 후에 '1'을 넘긴다.
  2. then 의 setTimeout 이 2초 후에 '1'을 출력하도록 등록하고, 그 다음 then 은 result 인자로 undefined 를 받는다.
  3. then 은 2초 후에 undefined를 출력하도록 등록하고 다시 그 다음 then 은 undefined 를 인자로 받는다.
  4. 마지막 then 도 2초 후에 undefined 를 출력하도록 등록한다.
  5. 2초 후 한번에 '1', undefined, undefined 가 출력된다.

따라서, 1, 12, 123 을 만드려면 then 안에 새로운 promise 객체를 만들어 반환해야 한다.

맞는 예시

function print(word) {
  return new Promise((resolve, reject)=> {
    setTimeout(()=> {
      console.log(word);
      resolve(word);
    }, 2000)
  })
}

// print() 는 새로운 promise 객체를 만들어 resolve 후 return 한다.
print('1') 
.then((result)=> { return print(result + '2'); })
.then((result)=> { return print(result + '3'); })
// 1 12 123

아까 코드와 다른 점은 매번 unsetteled 한 새 promise 를 만들어 반환하기 때문에, 매번 새로운 비동기 작업을 수행한다. 즉 print() 안에 있는 setTimeout 이 수행되고 resolve 가 될 때까지 return 을 하지 않는다. 따라서 2초마다 순차적으로 값이 나올 수 있다.

then 안에 새로운 Promise 를 만들어 리턴하는 방식은 다수의 비동기 작업을 순서에 맞게 실행하도록 만들어준다.

Fetch

fetch 함수는 서버에서 데이터를 가져올 때 사용한다.

let promise = fetch(url); 
// fetch 함수는 네트워크 요청을 하고 promise 객체를 return 한다.
// 이 Promise 는 response 객체를 resolve 하는데, response 객체 내부의 데이터는 완전히 다운로드되지 않은 상태다.
// 따라서 response 를 보려면 response.text() 메소드를 사용한다.
// .text() 메소드는 text 가 서버에서 완전히 다운로드되면 res.text 를 resolve 하는 promise 를 리턴한다.
fetch(url)
.then(res => res.text())
.then(text => console.log(text))

// res.text() 메소드는 raw json 을 보여준다. 
// parse 된 데이터를 보려면 res.json() 메소드를 사용한다.
fetch(url)
.then(res => res.json())
.then(data => console.log(data))

// Github API 를 이용한 예시
fetch('https://api.github.com/users/jhoryong')
.then(res => res.json())
.then(data => console.log(data.name)) // Horyong Jung

Promise Chaining
https://javascript.info/promise-basics

profile
게임과 프론트엔드에 관심이 많습니다.

0개의 댓글