4주차 비동기 통신과 Promise

시유야·2023년 3월 19일
0
post-thumbnail

01 js제어 흐름

😊자바스크립트는 다른 멀티스레드 프로그래밍 언어와 다르게 싱글 스레드 환경에서 비동기 동작을 처리한다. 싱글 스레드 비동기 환경을 구성하는 중요 요소 중 하나인 이벤트 루프에 대해 이해하면, js엔진 레벨에서의 비동기 코드 동작을 이해할 수 있다.

자바스크립트 엔진은 하나의 메인 스레드로 구성된다.

메인 스레드가 코드를 읽어서 한 줄씩 실행한다. 브라우저 환경에서는 유저 이벤트를 처리하고 화면을 그린다.

멀티스레드 언어 : 예)JAVA
10초 뒤에 실행되는 setTimeOut() 메서드를 만나면 새로운 또 하나의 스레드를 열고 그 멀티스레드는 10초동안 아무 동작도 하지 않고 기다리다가 10초 뒤에 동작하고 소멸한다.

싱글스레드 언어 : 예)javascript
10초 뒤에 실행되는 setTimeout()메서드를 읽으면 외부 Web API에서 10초 기다리다가 10초 후 실행이 되고 task Queue로 이동되어 메서드 저장이 되어있다가 하나뿐인 메인 스레드가 task Queue에서 저장되어 있던 setTimeout()메서드를 가지고 와서 실행을 한 후 소멸이 된다.

동기적 제어 흐름

  • 동기적 제어 흐름은 현재 실행 중인 코드가 종료되기 전까지 다음 줄의 코드를 실행하지 않는 것을 의미한다.
  • js에서도 분기문, 반복문, 함수 호출등이 동기적으로 실행이 되는데, 예를 들어 if문을 만나면 if문이 실행이 완료될 때까지 기다렸다가 다음 줄의 코드를 읽고 실행한다.
  • 싱글 스레드 환경에서 메인스레드를 긴 시간 점유하면, 프로그램을 멈추게 한다.
    예를 들어, 무한for문을 만나게 되면 js엔진이 브라우저 랜더링을 멈추게 할 수 있다. 그러나 JAVA와 같은 멀티스레드 프로그래밍 언어는 브라우저를 종료시키지는 않는다.

비동기적 제어 흐름

  • 비동기적 제어 흐름은 현재 실행 중인 코드가 종료되기 전에 다음 라인의 코드를 실행하는 것을 의미한다.
  • 프로미스, 콜백함수 호출하는 함수 등은 비동기적으로 실행된다.
  • 코드의 흐름과 실제 제어 흐름이 다르다.
  • 비동기 작업을 기다리는 동안 메인 스레드는 다른 작업을 처리한다.

02 이벤트 루프

자바스크립트 엔진은 비동기 처리를 제공하지 않는다. 대신 비동기 코드는 정해진 함수를 제공하여 활용할 수 있는데 이 함수들을 'API' 라고 한다.
비동기 API 의 예시로, setTimeout, XMLHttpRequest, fetch 등의 Web API가 존재한다.
node.js의 경우 파일처리API, 암호화API등을 제공한다.

//타이머 비동기 처리
setTimeout(() => console.log('타이머 끝'), 1000);
setInterval(() => console.log('인터벌 타이머'), 1000);

//네트워크 처리 
fetch('https://google.com')
.then(() => console.log('네트워크 요청 성공'))
.catch(() => console.log('네트워크 요청 실패'));

비동기 처리 모델

비동기 코드를 처리하는 모듈은 js엔진 외부에 있다.

  • 이벤트 루프, task queue, job queue 등으로 구성된다.
  • API모듈은 비동기 요청을 처리 후 task queue에 콜백 함수를 넣는다.
  • js 엔진은 call stack이 비워지면, task queue의 콜백함수를 실행한다.

따라서 js코드는 js엔진 외에도 api모듈, 비동기코드를 처리하는 모듈 등이 함꼐 동작한다.

👌이벤트 루프는 콜 스택이 비워지는 것을 기다렸다가, 태스크 큐에서 콜백함수가 들어온 순서대로 함수를 꺼내 콜스택에 넣는다.
👌queue는 여러 개가 존재하며 그 중 우선 순위가 높은 큐 (job queue 등)에서 나중에 들어온 콜백함수가 실행될 수 있다.

03 Promise

비동기API중 하나이다.
task queue가 아닌 job queue(task queue보다 우선순위가 높음!!)를 사용한다.

  • 비동기 작업을 표현하는 js객체.
  • 비동기 작업의 진행, 성공, 실패 상태를 표현하여 비동기 처리의 순서를 표현할 수 있다.

Promise생성자

let promise = new Promise((resolve, reject) => {
  if (Math.random() < 0.5) {
    return reject('실패');
  }
  resolve(10);
})```
* new Promise(callback)
* callback함수는 (resolve, reject) 두 인자를 받는다. 
* Promise가 성공했을 때 → resolve를 호출하여 10을 찍는다.
* Promise가 실패했을 때 → reject를 호출하며 '실패'가 찍힌다. 

😊Promise API를 사용하면 비동기 처리에 의한 성공, 실패를 설정하여 확인 할 수 있다.

## promise 메서드 ( then, catch, finally)
``` js
promise.then(data => {  //.then() 메서드에 성공시 실행할 콜백함수를 인자로 넘김
  console.log('성공: ', data);
})
.catch(e => {  //.catch() 메서드에 실패시 실행할 콜백 함수를 인자로 넘김
  console.log('실패: ', e);
})
.finally(() => { //.finally()메서드는 성공/실패 여부와 상관없이 모두 실행할 콜백함수를 인자로 넘김
  console.log('promise종료');
})
  • .then(cb1, cb2) 로 cb1의 자리에 성공, cb2의 자리에 실패 메서드를 인자로 넘길 수 도 있다.

promise메서드 체인

  • .then/catch() 메서드가 또 다른 promise를 리턴하여, 비동기 코드에 순서를 부여한다.
  • 이렇게 동일한 객체에 메서드를 연결할 수 있는 것을 chaining이라고 한다.
  • 함수를 호출한 주체가 함수를 끝낸 뒤 자기 자신을 리턴하도록 하여 구현한다.
    new Promise() , .then() 끝에는 return this;가 생략되어 있는것

Promise 클래스 함수에 바로 사용이 가능한 정적 메서드가 존재한다.

인위적으로 Promise method chain을 만들 수 있어서, 비동기 코드로 진행해야 하는 상황 등에 유용하게 사용할 수 있다.

Promise.resolve

성공한 Promise를 바로 반환한다.

Promise.resolve(10).then(console.log);

Promise.reject

이 함수는 실패한 Promise를 바로 반환한다.

Promise.reject('Error').catch(console.log);

Promise.all

Promise.all([promise1, promise2, promise3])
.then(values => { 
  console.log('모두 성공:', values)
})
.catch(e => {
  console.log('하나라도 실패: ', e)
})
  • Promise.all()은 Promise 배열을 받아 모두 성공 시 각 Promise 의 resolved값을 배열로 반환한다.
  • 하나라도 실패시 가장 먼저 실패한 Promise 의 실패 이유를 반환한다.

newface용어

pending : 성공/실패 하기 전 진행 상태
setteld : 성공(resolved, fulfilled) / 실패(rejected) 상태를 묶어서 이르는 말

04 async/await

HTTP, REST API

Fetch API

profile
i'm happy enough.

0개의 댓글